20200406のlaravelに関する記事は12件です。

Laravel + Nuxtで現在地から最寄りのイベントを取得する

概要

現在、個人的に開発しているサービスで、ユーザの現在地から最寄りの開催中イベントを近い順に取得を行い
プルダウンで表示を行いたい

環境

Laravel 5.8
Nuxt 2.5.1

参考サイト

Laravel で MySQL の GEOMETRY 型のデータを扱いたかったので専用のトレイトをつくってみました

[laravel]緯度経度から最寄り駅を取得

laravel-mysql-spatial

実装方法

laravel-mysql-spatialをインストールする

composer require grimzy/laravel-mysql-spatial

マイグレーションファイルを作成

Laravelでは通常$table->geometry('location')と実装するが、laravel-mysql-spatialを使用する場合は$table->point('location')と実装する。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEventsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('events', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('operator_id');
            $table->unsignedBigInteger('currency_id');
            $table->string('event_name');
            $table->dateTime('opening_date')->nullable();
            $table->dateTime('end_date')->nullable();
            $table->string('prefectures'); // 都道府県
            $table->string('municipalities'); // 市町村
            $table->string('house_number'); //番地
            $table->string('building_name'); // 建物名
            $table->string('supplementary'); // 補足
            $table->point('location'); // 位置情報(緯度経度)
            $table->string('main_image_path')->nullable(); // イメージマップ画像
            $table->text('comment'); // コメント
            $table->integer('fee_division'); // 手数料区分 割合 or 固定
            $table->integer('opening_fee'); // XX% or XXXX円
            $table->timestamps();

            $table->index( 'operator_id' );
            $table->index( 'currency_id' );

            $table->foreign('operator_id')
                ->references('id')
                ->on('operators')
                ->onUpdate('cascade');

            $table->foreign('currency_id')
                ->references('id')
                ->on('currencies')
                ->onUpdate('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('events');
    }

}

モデルを作成

Eloquentで使用するためにprotected $spatialFieldsに対して、Geometry型のColumnを定義する。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;

class Event extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     *
     * @property \Grimzy\LaravelMysqlSpatial\Types\Point   $location
     */

    use SpatialTrait;

    protected $fillable = [
        'operator_id',
        'currency_id',
        'event_name',
        'opening_date',
        'end_date',
        'prefectures',
        'municipalities',
        'house_number',
        'building_name',
        'supplementary',
        'main_image_path',
        'comment',
        'fee_division',
        'opening_fee',
    ];

    protected $spatialFields = [
        'location',
    ];

    public function currency()
    {
        return $this->hasOne('App\Models\Currency', 'id');
    }
}

テストデータの挿入

EventsTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class EventsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('events')->insert([
            [
                'operator_id' => '1',
                'currency_id' => '1',
                'event_name' => '興正寺マルシェ',
                'prefectures' => '愛知県',
                'municipalities' => '名古屋市昭和区',
                'house_number' => '八事本町78',
                'building_name' => '',
                'supplementary' => '補足です',
                'location' => DB::raw("ST_GeomFromText('POINT(35.13988 136.96248)')"),
                'comment' => '「八事山興正寺」は、名古屋市昭和区にある真言宗のお寺です。
都会の中にあって美しい自然が昔からの姿で残ります。
重要文化財である五重塔がみえる入り口すぐの境内にて毎月21日に定期開催しています。
こだわりの農産物や加工食品、工芸品はもちろんペットのお散歩もできる境内ならではのペットブースもあります。',
                'fee_division' => '1',
                'opening_fee' => '10',
            ]
        ]);

        DB::table('events')->insert([
            [
                'operator_id' => '1',
                'currency_id' => '2',
                'event_name' => 'ミッドランドマルシェ',
                'prefectures' => '愛知県',
                'municipalities' => '名古屋市中村区',
                'house_number' => '名駅4丁目7-1(ミッドランドスクエア南側広場)',
                'building_name' => '',
                'supplementary' => '補足です',
                'location' => DB::raw("ST_GeomFromText('POINT(35.17000 136.88518)')"),
                'comment' => '名古屋駅前のランドタワー「ミッドランドスクエア」で名古屋駅エリア初開催。大人のラグジュアリーモールの広場ならではのちょっぴりお洒落なマルシェをお楽しみ下さい。。',
                'fee_division' => '1',
                'opening_fee' => '10',
            ]
        ]);
    }
}

APIの実装

APIは現在イベントが開催中かつ、現在の位置情報をもとに最寄りの10件を取得する

   /**
     * 購入者が現在参加できるイベントをコンボボックスに表示するためにイベント情報一覧を取得を行う
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(request $request){

        // バリデーションルール
        $validator = Validator::make($request->all(), [
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        // バリデーションエラーだった場合
        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()->toArray()
            ], 422);
        }

        // 現在の開催中かつ最寄り10件のイベント情報を取得する
        $events = Event::where('end_date', '>=', Carbon::now())
            ->orderByRaw('ABS(Y(location) - ? ) + ABS(X(location) - ? )', [$request->input('latitude'), $request->input('longitude')])
            ->limit(10)
            ->get();

        return response()->json([
            'success' => true,
            'data' => $events,
        ], 200);

    }

まとめ

位置情報を扱うのも提供ライブラリがあり、すんなり実装できた
最近アサインされたPJは、ドメイン駆動設計などを取り入れていて
そのうちでかくなってきたらこっちにも取り入れたいなと思ってます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel + Nuxtで現在地から最寄りのイベントを取得する(Laravel API編)

概要

現在、個人的に開発しているサービスで、ユーザの現在地から最寄りの開催中イベントを近い順に取得を行い
プルダウンで表示を行いたい

環境

Laravel 5.8
Nuxt 2.5.1

参考サイト

Laravel で MySQL の GEOMETRY 型のデータを扱いたかったので専用のトレイトをつくってみました

[laravel]緯度経度から最寄り駅を取得

laravel-mysql-spatial

実装方法

laravel-mysql-spatialをインストールする

composer require grimzy/laravel-mysql-spatial

マイグレーションファイルを作成

Laravelでは通常$table->geometry('location')と実装するが、laravel-mysql-spatialを使用する場合は$table->point('location')と実装する。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEventsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('events', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('operator_id');
            $table->unsignedBigInteger('currency_id');
            $table->string('event_name');
            $table->dateTime('opening_date')->nullable();
            $table->dateTime('end_date')->nullable();
            $table->string('prefectures'); // 都道府県
            $table->string('municipalities'); // 市町村
            $table->string('house_number'); //番地
            $table->string('building_name'); // 建物名
            $table->string('supplementary'); // 補足
            $table->point('location'); // 位置情報(緯度経度)
            $table->string('main_image_path')->nullable(); // イメージマップ画像
            $table->text('comment'); // コメント
            $table->integer('fee_division'); // 手数料区分 割合 or 固定
            $table->integer('opening_fee'); // XX% or XXXX円
            $table->timestamps();

            $table->index( 'operator_id' );
            $table->index( 'currency_id' );

            $table->foreign('operator_id')
                ->references('id')
                ->on('operators')
                ->onUpdate('cascade');

            $table->foreign('currency_id')
                ->references('id')
                ->on('currencies')
                ->onUpdate('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('events');
    }

}

モデルを作成

Eloquentで使用するためにprotected $spatialFieldsに対して、Geometry型のColumnを定義する。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;

class Event extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     *
     * @property \Grimzy\LaravelMysqlSpatial\Types\Point   $location
     */

    use SpatialTrait;

    protected $fillable = [
        'operator_id',
        'currency_id',
        'event_name',
        'opening_date',
        'end_date',
        'prefectures',
        'municipalities',
        'house_number',
        'building_name',
        'supplementary',
        'main_image_path',
        'comment',
        'fee_division',
        'opening_fee',
    ];

    protected $spatialFields = [
        'location',
    ];

    public function currency()
    {
        return $this->hasOne('App\Models\Currency', 'id');
    }
}

テストデータの挿入

EventsTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class EventsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('events')->insert([
            [
                'operator_id' => '1',
                'currency_id' => '1',
                'event_name' => '興正寺マルシェ',
                'prefectures' => '愛知県',
                'municipalities' => '名古屋市昭和区',
                'house_number' => '八事本町78',
                'building_name' => '',
                'supplementary' => '補足です',
                'location' => DB::raw("ST_GeomFromText('POINT(35.13988 136.96248)')"),
                'comment' => '「八事山興正寺」は、名古屋市昭和区にある真言宗のお寺です。
都会の中にあって美しい自然が昔からの姿で残ります。
重要文化財である五重塔がみえる入り口すぐの境内にて毎月21日に定期開催しています。
こだわりの農産物や加工食品、工芸品はもちろんペットのお散歩もできる境内ならではのペットブースもあります。',
                'fee_division' => '1',
                'opening_fee' => '10',
            ]
        ]);

        DB::table('events')->insert([
            [
                'operator_id' => '1',
                'currency_id' => '2',
                'event_name' => 'ミッドランドマルシェ',
                'prefectures' => '愛知県',
                'municipalities' => '名古屋市中村区',
                'house_number' => '名駅4丁目7-1(ミッドランドスクエア南側広場)',
                'building_name' => '',
                'supplementary' => '補足です',
                'location' => DB::raw("ST_GeomFromText('POINT(35.17000 136.88518)')"),
                'comment' => '名古屋駅前のランドタワー「ミッドランドスクエア」で名古屋駅エリア初開催。大人のラグジュアリーモールの広場ならではのちょっぴりお洒落なマルシェをお楽しみ下さい。。',
                'fee_division' => '1',
                'opening_fee' => '10',
            ]
        ]);
    }
}

APIの実装

APIは現在イベントが開催中かつ、現在の位置情報をもとに最寄りの10件を取得する

   /**
     * 購入者が現在参加できるイベントをコンボボックスに表示するためにイベント情報一覧を取得を行う
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(request $request){

        // バリデーションルール
        $validator = Validator::make($request->all(), [
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        // バリデーションエラーだった場合
        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()->toArray()
            ], 422);
        }

        // 現在の開催中かつ最寄り10件のイベント情報を取得する
        $events = Event::where('end_date', '>=', Carbon::now())
            ->orderByRaw('ABS(Y(location) - ? ) + ABS(X(location) - ? )', [$request->input('latitude'), $request->input('longitude')])
            ->limit(10)
            ->get();

        return response()->json([
            'success' => true,
            'data' => $events,
        ], 200);

    }

まとめ

位置情報を扱うのも提供ライブラリがあり、すんなり実装できた
最近アサインされたPJは、ドメイン駆動設計などを取り入れていて
そのうちでかくなってきたらこっちにも取り入れたいなと思ってます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCode の Remote - SSH機能を使ってConoha VPS上でLaravelの開発環境を構築する

はじめに

この記事ではConoha VPSへのLaravelの導入から、VSCodeのRemote-SSH機能を使っての開発環境の構築まで説明していきます。執筆時点で使っているVScodeのverは1.43.2です。

Conoha VPS上でLaravelの環境を用意する

※Conoha VPSに既にサインアップしている前提で説明します。

サーバ構成を選択する画面でLaravelを選択して追加する

Conoha VPSにはOSの他にもアプリケーションテンプレートなど、環境に応じて便利なテンプレートが多数用意されてます。
Laravelテンプレートも用意されており、選択して追加を押せば、裏側で必要なパッケージのインストールも同時に行ってくれる為、簡単にLaravelの環境を作成する事ができます。

badf1d00-74dd-11ea-820c-d4f51f3edf40.png

追加する際に、rootパスワードを設定しますが、こちらのパスワードは一度設定すると変更ができないので必ずどこかにメモをしてください。また、紛失した際にも確認する術がない為注意してください。

Q.VPSの管理者パスワードはどこで分かりますか?
A.ConoHaではメールなどでお伝えしておりません。VPS作成時に設定したrootパスワードは紛失しないようお客様ご自身での管理をお願いいたします。

ref:仕様について|ConoHa VPSサポート

追加が終わるとConoha VPSの管理画面に移ります。

b74b9600-74dd-11ea-80d7-47de0a57a8fb.png

Conoha VPSのコンソールパネルからLaravelがインストールされている場所を確認する

ネームタグをクリックして、サーバ情報のページに遷移します。

image.png

「コンソール」と書かれているボタンをクリックしてコンソールパネルを開きます。

image.png

log inにはrootを指定してください。
Passwordには先程設定したrootパスワードを入力してください。
(※もしrootパスワードに@を含めている方は注意してください。@がコンソール内だと「`」に変換されて入力されてしまいます。コンソール内で「`」を入力すると@に変換されます。)

ログインに成功すると、以下のような画面が出てきます。

image.png

ここまで出来たら、後はLaravelがあるディレクトリに移動して、インストールされているLaravelのバージョンを確認してみましょう。以下のコマンドを実行してConoha VPSに入っているLaravelのバージョンを確認します。

cd /var/www/html/laravel/
php artisan -V

これでConoha VPS上でLaravelの環境を作成して確認する事ができたので、次はVSCode の Remote–SSH機能を使って、VPS上のファイルを編集する作業を行いましょう。

VSCodeにRemote-SSHを入れて、Conoha VPS上のファイルを編集する

リモート接続する為の設定ファイルを生成する

まず最初にRemote-SSHで必要となる公開鍵と秘密鍵を設定していきます。
最初に秘密鍵を置いておくディレクトリと、リモートサーバーの接続する際に利用される設定ファイルも生成しておきます。
(※既にある場合はここはスキップして大丈夫です)

mkdir ~/.ssh 
touch ~/.ssh/config #設定ファイル

.ssh/configがどんな設定ファイルかについてはこの記事で省略しますが、興味があればこちらの記事をご覧ください。

ref:~/.ssh/configについて

Conoha VPSの管理画面で公開鍵を登録する

Conoha VPSの管理画面に戻り「セキュリティ」から「SSH Key」を選択します。

image.png

「パブリックキー」を押して、公開鍵を登録します。
登録ができると、秘密鍵をダウンロードするようポップアップが出るので、ダウンロードします。

image (4).png

秘密鍵をダウンロードしたら、~/.ssh/に移動させておいてください。
後ほどconfigの設定で説明が出てきますが、~/.ssh/で秘密鍵のパスさえ指定できれば問題ないです。
ただ、後で設定のパスを指定する際に混乱が減るので .sshディレクトリ配下に移しておくのを推奨します。

VSCodeにRemote-SSHをインストールする

VSCodeの拡張機能の検索画面からRemote-SSHを検索してインストールします。

image.png

インストールが完了するとVSCodeの左のアイコン一覧にRemote-SSH用のアイコンが表示されます。

image.png

.ssh/configにConoha VPSの設定を記述する

{}で囲っている箇所は自分の環境に合わせて変更してください。

Host {名前}
HostName {IPアドレス}
User root
Port 22
IdentityFile {秘密鍵が置いてあるパスを指定する}

Hostは自由に設定してください。
HostNameには、Conoha VPSで作成したサーバのIPアドレスを指定します。

image.png

IdentityFileはダウンロードした秘密鍵が置いてあるディレクトリのパスを指定します。
.sshディレクトリ配下に置いている場合、パスの指定は以下のようになります。

IdentityFile ~/.ssh/{秘密鍵の名前}

これで、.ssh/configの設定は完了です。

VSCodeからConoha VPSに接続する

完了後にRemote-SSHのアイコンを更新すると、Hostで指定した名前で出てきます。

右クリックを押すと、今のウィンドウで開くか、新しいウィンドウで開くか選択できるので選んで、Conoha VPSにリモート接続します。

image.png

接続の途中でrootパスワードを聞かれるので入力してください。
認証に成功すると接続している事がわかるようにフッターが紫になります。

image.png

VSCodeのエクスプローラーからConoha VPS上のLaravelがインストールされているディレクトリを開きます。
コマンドパレットにlaravelがインストールされているパスを指定します。

var/www/html/laravel

image.png

OKを押すと、エクスプローラーにlaravelのディレクトリ構成が表示されます。

これで、VSCodeからConoha VPSに接続してエディターで、ファイルを編集する環境が出来ました。

VSCodeのターミナル画面からConoha VPS上のファイルを操作するようbashを指定する

デフォルトだと、 VSCodeのターミナルを開いても設定がなく、ローカルの設定が読み込まれてしまってターミナルが開かない場合があります。その場合は、リモート接続しているサーバ上のbashが読み込まれるよう設定を加えます。

設定方法としてはVSCodeの基本設定のコマンドパレットに「ターミナル」を入れて、設定画面を出します。

image.png

「リモート」を選択してAutomation Shell:Linuxの下にあるsetting.jsonで編集を開いて、bashのパスを指定します。
Conoha VPSでは/usr/bin/配下にbashがあります。

{
    "terminal.integrated.shell.linux": "/usr/bin/bash"
}

この状態で保存をしてターミナルを開くと、Conoha VPS上に接続した状態でサーバのターミナルを操作する事ができます。
試しにphp artisan -Vで確認してみましょう。

image.png

マイグレーションを行う

[近日中に書きます]

参考資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCode の Remote - SSH機能を使ってConoha VPS上でLaravelの開発環境を用意する

はじめに

この記事ではConoha VPSへのLaravelの導入から、VSCodeのRemote-SSH機能を使っての開発環境の構築まで説明していきます。

執筆時点での自分の環境を載せておきます。

version
macOS Mojave 10.14.16
VSCode 1.43.2

Conoha VPS上でLaravelの環境を用意する

※Conoha VPSに既にサインアップしている前提で説明します。

サーバ構成を選択する画面でLaravelを選択して追加する

Conoha VPSにはOSの他にもアプリケーションテンプレートなど、環境に応じて便利なテンプレートが多数用意されてます。
Laravelテンプレートも用意されており、選択して追加を押せば、裏側で必要なパッケージのインストールも同時に行ってくれる為、簡単にLaravelの環境を作成する事ができます。

badf1d00-74dd-11ea-820c-d4f51f3edf40.png

追加する際に、rootパスワードを設定しますが、こちらのパスワードは一度設定すると変更ができないので必ずどこかにメモをしてください。また、紛失した際にも確認する術がない為注意してください。

Q.VPSの管理者パスワードはどこで分かりますか?
A.ConoHaではメールなどでお伝えしておりません。VPS作成時に設定したrootパスワードは紛失しないようお客様ご自身での管理をお願いいたします。

ref:仕様について|ConoHa VPSサポート

追加が終わるとConoha VPSの管理画面に移ります。

b74b9600-74dd-11ea-80d7-47de0a57a8fb.png

Conoha VPSのコンソールパネルからLaravelがインストールされている場所を確認する

ネームタグをクリックして、サーバ情報のページに遷移します。

image.png

「コンソール」と書かれているボタンをクリックしてコンソールパネルを開きます。

image.png

log inにはrootを指定してください。
Passwordには先程設定したrootパスワードを入力してください。

(※もしrootパスワードに@を含めている方は注意してください。キーボードによっては@がコンソール内だと「`」に変換されて入力されてしまいます。コンソール内で「`」を入力すると@に変換されます。自分が職場で使っているUS配列のキーボードだと上記の問題が起きた為注意書きとして残しておきます。)

ログインに成功すると、以下のような画面が出てきます。

image.png

MySQLのパスワードは後ほど、マイグレーションの所で使うのでメモしておきます。

ここまで出来たら、後はLaravelがあるディレクトリに移動して、インストールされているLaravelのバージョンを確認してみましょう。以下のコマンドを実行してConoha VPSに入っているLaravelのバージョンを確認します。

cd /var/www/html/laravel/
php artisan -V

これでConoha VPS上でLaravelの環境を作成して確認する事ができたので、次はVSCode の Remote–SSH機能を使って、VPS上のファイルを編集する作業を行いましょう。

VSCodeにRemote-SSHを入れて、Conoha VPS上のファイルを編集する

リモート接続する為の設定ファイルを生成する

まず最初にRemote-SSHで必要となるパブリックキーとシークレットキーを設定していきます。
パブリックキーはブラウザで登録して、シークレットキーはローカルに落として使います。

最初にシークレットキーを置いておくディレクトリと、リモートサーバーの接続する際に利用される設定ファイルも生成しておきます。
(※既にある場合はここはスキップして大丈夫です)

mkdir ~/.ssh 
touch ~/.ssh/config #設定ファイル

.ssh/configがどんな設定ファイルかについてはこの記事で省略しますが、興味があればこちらの記事をご覧ください。

ref:~/.ssh/configについて

Conoha VPSの管理画面でパブリックキーを登録する

Conoha VPSの管理画面に戻り「セキュリティ」から「SSH Key」を選択します。

image.png

「パブリックキー」を押して登録します。
登録ができると、シークレットキーをダウンロードするようポップアップが出るので、ダウンロードします。

image (4).png

シークレットキーをダウンロードしたら、~/.ssh/に移動させておいてください。
後ほどconfigの設定で説明が出てきますが、~/.ssh/でシークレットキーが置いてある場所のパスを指定できれば問題ないです。
ただ、後で設定のパスを指定する際に混乱が減るので .sshディレクトリ配下に移しておくのを推奨します。

VSCodeにRemote-SSHをインストールする

VSCodeの拡張機能の検索画面からRemote-SSHを検索してインストールします。

image.png

インストールが完了するとVSCodeの左のアイコン一覧にRemote-SSH用のアイコンが表示されます。

image.png

.ssh/configにConoha VPSの設定を記述する

{}で囲っている箇所は自分の環境に合わせて変更してください。

Host {名前}
HostName {IPアドレス}
User root
Port 22
IdentityFile {秘密鍵が置いてあるパスを指定する}

Hostは自由に設定してください。
HostNameには、Conoha VPSで作成したサーバのIPアドレスを指定します。

image.png

IdentityFileはダウンロードしたシークレットキーのパスを指定します。
.sshディレクトリ配下に置いている場合、パスの指定は以下のようになります。

IdentityFile ~/.ssh/{シークレットキーの名前}

これで、.ssh/configの設定は完了です。

VSCodeからConoha VPSに接続する

完了後にRemote-SSHのアイコンを更新すると、Hostで指定した名前で出てきます。

右クリックを押すと、今のウィンドウで開くか、新しいウィンドウで開くか選択できるので選んで、Conoha VPSにリモート接続します。

image.png

接続の途中でrootパスワードを聞かれるので入力してください。

image.png

認証に成功するとフッターにHostの名前が表示されます。

image.png

VSCodeのエクスプローラーからConoha VPS上のLaravelがインストールされているディレクトリを開きます。
コマンドパレットにlaravelがインストールされているパスを指定します。

var/www/html/laravel

image.png

OKを押すと、エクスプローラーにlaravelのディレクトリ構成が表示されます。

これで、VSCodeからConoha VPSに接続してエディターで、ファイルを編集する環境が出来ました。

VSCodeのターミナル画面からConoha VPS上のファイルを操作するようbashを指定する

デフォルトだと、 VSCodeのターミナルを開いても設定がなく、ローカルの設定が読み込まれてしまってターミナルが開かない場合があります。その場合は、リモート接続しているサーバ上のbashが読み込まれるよう設定を加えます。

設定方法としてはVSCodeの基本設定のコマンドパレットに「ターミナル」を入れて、設定画面を出します。

image.png

「リモート」を選択してAutomation Shell:Linuxの下にあるsetting.jsonで編集を開いて、bashのパスを指定します。
Conoha VPSでは/usr/bin/配下にbashがあります。

{
    "terminal.integrated.shell.linux": "/usr/bin/bash"
}

この状態で保存をしてターミナルを開くと、Conoha VPS上に接続した状態でサーバのターミナルを操作する事ができます。
試しにphp artisan -Vで確認してみましょう。

image.png

Conoha VPS上で マイグレーションを行う

リモートに接続ができたら、DBと接続してマイグレーションを行います。
最初のConoha VPSのコンソールでログインしたときの画面を思い出してください。

image.png

こちらのMySQL Passoword.envファイルに追記します

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD={MySQL Passoword}

Laravel側の設定としてはこれで終わりですが、このままではまだマイグレーションが出来ません。
Conoha VPSのMySQLにアクセスして、接続するdatabaseを作成します。
.envを見るとlaravelが指定されてますが、実際にMySQLにログインすると

# mysql -uroot -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 5.5.64-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.01 sec)

laravelというDBは存在しません。なので、直接SQLを叩いてDBを作ります。

REATE DATABASE laravel;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel            |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

これで出来たのでマイグレーションを実行します。しかし、このままではまだエラーが出てしまいます。

php artisan migrate

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))

このエラーの原因としてはLaravel5.4から標準charasetがutf8mb4に変わりましたが、この形式に対応できるMySQLのverは5.7.7です。
しかし、Conoha VPSで稼働しているMySQLのverが5.5の為、ユニーク制約を付けたカラムを設定する際に、指定サイズが超えてしまい、エラーになります。

詳細:Laravel5.4以上、MySQL5.7.7未満 でusersテーブルのマイグレーションを実行すると Syntax error が発生する - Qiita

対応方法としてはいくつかあるのですが、Laravelでテーブルのスキームを定義する際の最大長未指定時のdefault値を指定サイズ以下に抑えるよう設定します。

設定先ファイルはapp\Providers\AppServiceProvider.phpです。

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

この状態であればConoha VPS上で問題なくマイグレーションが出来る状態になります。

# php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.02 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0 seconds)

実際にテーブルが出来ているかを確認します。

MariaDB [laravel]> show tables;
+-------------------+
| Tables_in_laravel |
+-------------------+
| failed_jobs       |
| migrations        |
| users             |
+-------------------+
3 rows in set (0.00 sec)

以上でマイグレーションの説明は終わりです。

やる事は沢山あるのですが、1つ1つ完了していけば、詰まらずに構築できると思います!
お疲れ様でした。

参考資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHub Actions(+Heroku)を使用してLaravelのCI/CD環境を作成する

前提条件

  • GitHubにLaravelの環境が設定済み
  • HerokuにLaravelアプリケーションが構築ずみ

GitHub Actionsの設定を行う

Laravel用のテンプレートがあるのでこれを選んでカスタマイズする。

Image from Gyazo

example.yml
name: example

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:10.8
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: test
        ports:
        - 5432:5432
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

    steps:
    - uses: actions/checkout@v2
    - name: Copy .env
      run: cp .env.ci .env
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: Execute Migration
      run: php artisan migrate --force
    - name: Execute Seed
      run: php artisan db:seed --force
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      run: vendor/bin/phpunit
  • PostgreSQLのバージョンとかは任意

.env.ciの作成

env.ci
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=test
DB_USERNAME=postgres
DB_PASSWORD=postgres

Heroku側の設定

Image from Gyazo

  • Heroku側の管理画面からApp connected to GitHubでボタンをぽちぽちして、GitHubとの連携をONにする。

Image from Gyazo

  • Heroku側の管理画面からAutomatic deploysでボタンをぽちぽちして、GitHubとの連携をONにする。

Procfileの編集

- Procfileを編集してマイグレーションとかSeederを自動化する

release: php artisan migrate --force && php artisan db:seed --force
web: vendor/bin/heroku-php-apache2 public/

後はPull Request時にGitHubActionsでTestの結果を待つ。

Image from Gyazo

続いてMergeしてHerokuのデプロイ状況が確認できればOK。

Image from Gyazo

Image from Gyazo

参考

Using Github Actions to setup CI/CD with Laravel (and MySQL)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel6.xでよく使うコマンド一覧 〜マイグレーションからモデルやコントローラ作成まで〜

個人的によく使うコマンドの使用例

コマンド一覧を見てもオプション関係がゴッチャになるので、定型文的によく使うLaravelのコマンドをメモ。
バージョンはLaravel 6.x です。最近リリースされた7では確認していませんが、確認が取れたらまた更新します。

マイグレーション関連

Composerのオートローダを再生成

composer dump-autoload

シーダクラスを作成した後などは、Composerのオートローダを再生成するためにこちらのコマンドを実行する必要があります。
シーディングやマイグレーション時にデータベースのエラーが出るときは大体このコマンドを忘れているパターンが多いです。
上記コマンドを打たなくてもエラーにならない場合もあり、例えば元々あったシーダーを編集してシーディングし直すときは必要なさそうでした。

マイグレーションファイルの作成

php artisan make:migration create_users_table --table=users

オプションを付加しながらマイグレーションファイルの作成。--table=の後にテーブル名を記載します。
コマンドを実行した日時によって、例えば下記のように、 年_月_日_時間+指定した名前 といったファイル名でマイグレーションファイルは作成されます。
2020_02_19_155441_create_users_table.php

テーブル作成だけでなく、「カラムの修正」や「外部キーの設定」とか、操作したい内容によって modify_colmn_type_user_id_on_users.phpadd_foreign_keys_to_users_tableなど、わかりやすい名前にすると良いかと思います。

シーダーファイルの作成

php artisan make:seeder UsersTableSeeder

データベースにテストデータを流し込むための入れ物を作ります。
今回の場合はUsersテーブル用のシーダーということになります。
テーブル名は各自で適切なものを設定してください。

マイグレーションのやり直しと同時にシーディング

php artisan migrate:fresh --seed

今あるテーブルを全ドロップしてテーブルを作り直し、DatabaseSeeder.phpに登録されたシーダーを同時に実行します。

php artisan migrate:refresh などでエラーになったときは、この php artisan migrate:fresh で解消することもあります。

シーディングのみ実行

php artisan db:seed

マイグレーションとは別にDatabaseSeeder.phpに登録されたシーディングだけ実行したいときはこちらのコマンドを打ちます。

特定のシーダー、クラスのシーディングのみ実行

php artisan db:seed --class=UsersTableSeeder

DatabaseSeeder.phpに登録していないものや、登録はしたが個別にシーダーを実行したいという際に使用します。
--class=の後にシーダーのクラス名を指定すればOKです。

モデル・コントローラ関連

モデル作成

php artisan make:model User

モデルを作ります。通常Laravelでは、テーブル名は複数形、モデル名はテーブル名の単数形とします。

モデルと同時にコントローラ作成

php artisan make:controller UserController

コントローラを作ります。こちらもテーブル名の単数形が良いです。
指定した名前でコントローラが作成され、今回の場合はUserController.phpというファイル名になります。

php artisan make:controller UserController --model=Models/User

モデルも一緒に作成したい場合は後ろにオプションを付けて作成可能です。
--model=Userとすればappディレクトリ配下にUser.phpのモデル用ファイルができますが、モデル用のディレクトリを切って管理したい場合などは --model=Models/User とすればapp/Modelsのディレクトリ配下にモデルが作成されます。

php artisan make:controller UserController --resource

自分でイチからfunctionを書かなくても、最初からCRUD処理用のメソッドをpublic functionとして最初に用意しておいてくれるのが上記のように --resource のオプションを付けた場合です。
これらは下記のように繋げて書くことで一度に実行できます。

php artisan make:controller UserController --resource --model=Models/User

--resource のオプションを付けた場合は、公式のドキュメントにあるように、下記のルートに紐づけられるメソッドが入れ物として用意されていますので、メソッドの内容は開発時に適宜上書きしていきます。

 動詞       | URI                  | アクション | ルート名
------------------------------------------------------------------
 GET       | /photos              | index   | photos.index
 GET       | /photos/create       | create  | photos.create
 POST      | /photos              | store   | photos.store
 GET       | /photos/{photo}      | show    | photos.show
 GET       | /photos/{photo}/edit | edit    | photos.edit
 PUT/PATCH | /photos/{photo}      | update  | photos.update
 DELETE    | /photos/{photo}      | destroy | photos.destroy

このリソースフルな状態でコントローラを作成すれば、下記のようにルートを定義すれば1行ですべてをまかなえます。

web.php
Route::resource('photos', 'PhotoController');

ただ自分はすべてのリソースを使う必要がなく、URL(URI)も/photos/{photo}/edit等から変更したいということも多く、割と従来通りに自分でルートの定義はしていたりします。

今日はいったんそんな感じです。

参考URL

■マイグレーション -> Laravel 6.x データベース:マイグレーション
■シーディング -> Laravel 6.x データベース:シーディング
■モデル -> Laravel 6.x Eloquent:利用の開始
■コントローラ -> Laravel 6.x コントローラ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのroutingでprefixにパラメーターを入れる事ができる

LaravelでRestAPIライクなURLを設定する時には、prefix内にパラメーターを設定すると子のroute側でパラメーターが受け取れます。

/posts/{id}/comments
/posts/{id}/recommends

というようなAPIを作成するとします。

以下のようにしてRouteのところにidを入れてURLを指定することも出来ますが、

api.php
Route::prefix('posts')->group(function () {
    Route::get('/{id}/comments', 'PostController@comments');
    Route::get('/{id}/recommends', 'PostController@recommends');
});

以下のようにprefixにパラメーターを入れる形でもControllerのメソッド側でidをパラメーターとして受け取ることが出来ます。

api.php
Route::prefix('posts/{id}')->group(function () {
    Route::get('/comments', 'PostController@comments');
    Route::get('/recommends', 'PostController@recommends');
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

さくらのレンタルサーバで Laravel を使うメモ (2020/04)

ぐぐって出てくる記事からバージョンが変わってたりして、うまく動かないことが結構あったので、現時点(2020/04)で動くまで持っていったときのメモ。

用意

  • さくらのレンタルサーバ:スタンダード
  • ssh の使える手元の PC

手順

サーバとローカル PC に composer をインストールする。完全にローカル PC でしか composer を使わないなら、サーバ側に入れる必要はない。

% cd
% curl -sS https://getcomposer.org/installer | php

これで、カレントに composer.pharができるので、$HOME/binmv する。

% mv composer.phar ~/bin/composer
% rehash

デフォルトで $HOME/bin にパスが通っているはずだけど、通ってなければ ~/.cshrc を書きかえる。

set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin)

composer の実行ができるかを確認する。

% composer -V
Composer version 1.10.1 2020-02-30 25:61:99

これで準備はおわり。

プロジェクトの作成

さくらサーバ上で作成しようとすると、途中でプロセスが kill されるっぽいので、ローカルの PC で作っておく。

$ composer create-project laravel/laravel sample

sample 以下にプロジェクトが作成される。ローカル側では下記のコマンドで動作を確認できる。

$ cd sample; php artisan serve

http://localhsot:8000/ で動作確認できる。

作成したプロジェクトを zip するなり、github に push するなりして、サーバ側にもっていく。以下は zip する場合。scp や ssh 時にはサーバのパスワードが必要。(name はさくらのサーバ名)

$ zip -r sample.zip ./sample
$ scp sample.zip name@name.sakura.ne.jp:~/
$ ssh name@name.sakura.ne.jp
...
% unzip sample.zip
% mv sample /home/name/www/

これで、ブラウザから http://name.sakura.ne.jp/sample/public/ でアクセスできるはず。

image.png

こんな感じの画面が出たら成功。

あとは、いろいろする。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelで作ったAPIを外部サーバーにおいて公開する話

はじめに

なぜ開発中のAPI外部サーバーにおいて公開することにしたのか。
なぜなら遠隔でフロントとバックの開発を同時並行で円滑に進めていくためです。

しかし、外部サーバーなど一度も使ったことがなかったのでいろいろ大変でした。

welcome画面を表示させるまで

Procfileを作成します。

Procfile
web: vendor/bin/heroku-php-apache2 public/

intlを有効化します。

アプリのホームディレクトリ
$ composer require ext-intl:*

ここからherokuの環境変数を設定していくわけなんですが、ここでまず詰まりました。

$ heroku config:set
 ›   Error: Missing required flag:
 ›     -a, --app APP  app to run command against
 ›   See more help with --help

はい、configを開こうとするとエラーが出ました。

$ heroku git:remote -a アプリ名

今までgithubと連携してそこからデプロイをしていたのですが、それが原因だったみたいです。herokuに直接デプロイすることで解決しました。
(他にも解決法はあると思います)

さあ、これでやっとwelcome画面が表示されるようになりました。

DB問題

ローカルではsqliteを使って開発していました。
herokuについて何も知らなかったのでそのままデプロイしたら使えるのだろう、と甘くみていました。
しかーし、何を試してもAPIを使おうとするとエラーを吐かれてしまいます。

なぜなら、答えは簡単「herokuはsqliteに対応していない」
herokuのDBはpgsqlだということです。
pgsqlは触ったことがなかったので、変更するならせめて触ったことのあるmysqlが精一杯でした。

どうやらherokuでもadd-onをインストールすればmysqlが使えるようになるらしいとの情報を入手。
それがこちらのClearDB
スクリーンショット 2020-04-06 0.27.37.png
このコマンドで無料版をインストールします。

$  heroku addons:create cleardb:ignite

ここでもエラーが出ました。

$ heroku addons:create cleardb:ignite
Creating cleardb:ignite on ⬢ アプリ名... !
 ▸    Please verify your account to install this add-on plan (please enter a credit card) For more information, see
 ▸    https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify

クレジットカード情報を入力することでこのエラーは解決します。

次にホスト名などを取得します

$ heroku config:get CLEARDB_DATABASE_URL

ここで返される値の内訳は以下の通りです。

mysql://[ユーザ名]:[パスワード]@[ホスト]/[DB名]?reconnect=true

ここで得た値をもとに環境変数を設定していきます。

$ heroku config:set \
> DB_CONNECTION=mysql \
> DB_HOST=[ホスト] \
> DB_DATABASE=[DB名] \
> DB_USERNAME=[ユーザー名] \
> DB_PASSWORD=[パスワード]

それではmigrate&seedをしていきます。

$ heroku run php artisan migrate --seed

ここでエラーが頻発しました。

  • uesrsテーブルのmigrateで問題発生

今回のAPIではusersテーブルは使用しなかったので、migrationファイルをコメントアウトして無効化するという強行策で解決。

  • どうやらmigrationの宣言の部分で問題発生

こちらも強行策で解決させました。

MySQLWorkbenchをインストールして、手動でテーブルを作成していきました。笑
スクリーンショット 2020-04-06 0.44.29.png
そして最後にseedでテストデータを入れます。

$ heroku run php artisan db:seed

これでやっとAPIが使えるようになりましたー!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Slackでモーダル(ダイアログ)を使ってデータを送信する

最近、弱々エンジニア会に参加しました。
記事貢献を兼ねて、久しぶりのQiita投稿です!
今回はSlackでSlackAppを使って、モーダル(ダイアログ)使ったデータの入出力を行う方法を解説していきたいと思います。

今回作るもの

/modal というSlashコマンドを実行すると Block Kit Builder で作られたモーダルを表示して、入力された値をサーバーに送るSlackアプリを作ります。
ezgif.com-video-to-gif (3).gif

参考資料

https://api.slack.com/surfaces/modals/using

開発環境

  • PHP 7.2 (Laravel 6.16)
  • GAE Standard (外部からアクセスできるサーバーであればなんでも可)
  • Slack (フリープランでも可)

実装方法

Slackアプリの用意

モーダルを出す方法がメインなので細かくは書きません。
細かい部分は 運用中のブログ にまとめてるので気になる方はご覧ください〜

アプリの作成

https://api.slack.com/apps から Create New App を選択して作っていきます。
slack-app-create.jpg

Slashコマンドの登録

適当にSlashコマンドを登録します。
slash-install.jpg

権限の設定

今回のサンプルであれば commands のみで作成できます。
※ Slashコマンドを登録すると勝手に入ると思います。
いけなかったら教えてください\(^o^)/

interactivity の設定

ダイアログに値を入力された後、その値が送られる向き先の設定をする必要があります。
interactivity.jpg

ワークスペースにインストール

Install App からインストールします。
表示に従っていればインストールできると思いますが、一点初回インストールの場合は下記のApp Display Name を設定しないと「インストールできるボットユーザーがありません」と怒られてしまいます。
apphome.jpg

以上でSlackの設定は終了です!(結構細かったかもしれん

コーディング

ようやく本編です。Laravelで書いていきます。
トークンとかは分けるべきなんですが、都合上まとめてますので良い感じで整理してください。

/modal が実行されたときの処理

Route::post('/modal', 'SlackController@modal')->name('modal');

な感じでSlackControllerにリクエストが飛んだ後の処理を書いていきます

SlackController.php(折り畳み)
<?php

namespace App\Http\Controllers;

use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

class SlackController extends Controller
{
    const BOT_TOKEN = 'xoxb-xxxxxxxx'

    /**
     * /modal のSlashコマンドを実行すると呼ばれる場所
     *
     * @param Request $request
     * @return Response
     */
    function modal (Request $request) {
        $url = 'https://slack.com/api/views.open';
        $token = self::BOT_TOKEN;
        $view = $this->getModalContent();
        $trigger_id = $request->input('trigger_id');

        $params = [
            'view' => \GuzzleHttp\json_encode($view),
            'trigger_id' => $trigger_id
        ];

        $headers = [
            'Content-type' => 'application/json',
            'Authorization'  =>  'Bearer ' . $token
        ];

        $client = new Client();
        $response = $client->request(
            'POST',
            $url, // URLを設定
            [
                'headers' => $headers,
                'json' => $params
            ] // パラメーターがあれば設定
        );

        $log = \GuzzleHttp\json_decode($response->getBody()->getContents(), true);
        Log::info(print_r($log, true));

        return response('',200);
    }

    /**
     * ダイアログのテンプレートを作る
     *
     * @return array
     */
    function getModalContent () {
        return [
            "type" => "modal",
            "title" => [
                "type" => "plain_text",
                "text" => "メンバー登録",
                "emoji" => true
            ],
            "submit" => [
                "type" => "plain_text",
                "text" => "登録",
                "emoji" => true
            ],
            "close" => [
                "type" => "plain_text",
                "text" => "キャンセル",
                "emoji" => true
            ],
            "blocks" => [
                [
                    "type" => "input",
                    "block_id" => "name",
                    "element" => [
                        "type" => "plain_text_input",
                        "action_id" => "氏名",
                        "placeholder" => [
                            "type" => "plain_text",
                            "text" => "田中 太郎"
                        ],
                    ],
                    "label" => [
                        "type" => "plain_text",
                        "text" => "氏名"
                    ]
                ],
                [
                    "type" => "input",
                    "block_id" => "mail",
                    "element" => [
                        "type" => "plain_text_input",
                        "action_id" => "メールアドレス",
                        "placeholder" => [
                            "type" => "plain_text",
                            "text" => "xxx@gmail.com"
                        ],
                    ],
                    "label" => [
                        "type" => "plain_text",
                        "text" => "メールアドレス"
                    ]
                ],
                [
                    "type" => "input",
                    "block_id" => "language",
                    "optional" => true,
                    "element" => [
                        "type" => "checkboxes",
                        "action_id" => "得意言語",
                        "options" => [
                            [
                                "text" => [
                                    "type" => "plain_text",
                                    "text" => "PHP",
                                    "emoji" => true
                                ],
                                "value" => "value-0"
                            ],
                            [
                                "text" => [
                                    "type" => "plain_text",
                                    "text" => "Ruby",
                                    "emoji" => true
                                ],
                                "value" => "value-1"
                            ],
                            [
                                "text" => [
                                    "type" => "plain_text",
                                    "text" => "Javascript/Node.js",
                                    "emoji" => true
                                ],
                                "value" => "value-2"
                            ],
                            [
                                "text" => [
                                    "type" => "plain_text",
                                    "text" => "Python",
                                    "emoji" => true
                                ],
                                "value" => "value-3"
                            ]
                        ]
                    ],
                    "label" => [
                        "type" => "plain_text",
                        "text" => "得意言語",
                        "emoji" => true
                    ]
                ]
            ]
        ];
    }

ちなみに以下のライブラリを使用しています。
GuzzleHttp
Google StackDriver Logging

メイン処理ですが Slack API の view.open というAPIを利用しています。

$url = 'https://slack.com/api/views.open';

ダイアログの中身は Block Kit Builder で作ったものを使っていますが、細かい部分を修正しているので紹介します。

block_id と action_id は設定しておいたほうがいい

デフォルトでは付いていないのですが、 block_id と action_id はちゃんと設定したほうがいいです。
理由は次に紹介するパラメータの受け取り時にどの値なのかわからなくなりパラメータの取得が面倒になります。
それぞれ日本語も入れられたので結果を返す時にちゃっかり使っています。

optional の場所を間違えないで

地味にやらかしたのが optional の場所。
optionalを付けることで任意の値として設定できるようになりますが、 element の中 に入れてしまっていたので何回か詰まっていました。正しくは element の外 です。

正しく view.open が実行されていれば /modal を実行した時にダイアログは表示されるようになっているはずです。

モーダル経由で入力値を送られてきたときの処理

Route::post('/interactiveMessage', 'SlackController@interactiveMessage')->name('interactiveMessage');

な感じでSlackControllerにリクエストが飛んだ後の処理を書いていきます

SlackController.php(折り畳み)
<?php

namespace App\Http\Controllers;

use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

class SlackController extends Controller
{
    const BOT_TOKEN = 'xoxb-xxxxxxxx';

    // 先程のControllerに追記する形で

    /**
     * モーダルから送られてくるリクエストを受け取る
     *
     * @param Request $request
     * @return Response
     */
    function interactiveMessage (Request $request) {
        // 早期レスポンス
        response('',200)->send();

        $payload = $request->input('payload');
        $postData = \GuzzleHttp\json_decode($payload, true);

        Log::info(print_r($postData, true));

        switch ($postData['type']) {
            case 'view_submission':
                // submit された時

                /*
                 * なんらかの処理
                 */

                $text = '登録しました!';
                $user =  $postData['user']['id'];

                $attachments = $this->makeAttachments($postData['view']['state']['values']);

                Log::info(print_r($attachments, true));

                // メッセージを送る
                // modalを使う場合、response_urlを取得できなかったので強制的にメッセージ投稿
                $response = $this->postEphemeral($user, $text, $attachments);

                $log = \GuzzleHttp\json_decode($response->getBody()->getContents(), true);
                Log::info(print_r($log, true));
                break;
            case 'block_actions':
                // チェックボックスなどが更新された時
                break;
        }
    }

    /**
     * 「あなただけに表示されています」のメッセージを送る
     *
     * @param $user
     * @param $text
     * @param $attachments
     * @return mixed
     */
    function postEphemeral ($user, $text, $attachments = []) {
        $url = 'https://slack.com/api/chat.postEphemeral';
        $token = self::BOT_TOKEN;

        $params = [
            'token' => $token,
            'attachments' => \GuzzleHttp\json_encode($attachments),
            'channel' => $user,
            'text' => $text,
            'user' => $user,
        ];

        Log::info(print_r($params, true));

        $client = new Client();
        $response = $client->request(
            'POST',
            $url,
            ['query' => $params]
        );

        return $response;
    }

    /**
     * 回答を受け取った結果をまとめる
     *
     * @param $values
     * @return array
     */
    function makeAttachments ($values) {
        $text =  "";
        foreach ($values as $key => $value) {
            foreach ($value as $name => $detail) {
                switch ($detail['type']) {
                    case 'plain_text_input':
                        $text .= $name . ' : ' . $detail['value'] . "\n";
                        break;
                    case 'checkboxes':
                        $checkedValue = '';
                        if (isset($detail['selected_options'])) {
                            foreach ($detail['selected_options'] as $selected_option) {
                                $checkedValue .= $selected_option['text']['text'] . " ";
                            }
                        } else {
                            $checkedValue .=  '指定なし';
                        }

                        $text .= $name . ' : ' . $checkedValue . "\n";
                        break;
                }
            }
        }
        $attachments[] = [
            'text' => $text,
        ];
        return $attachments;

}

こちらも同様に注意すべきポイントを紹介します。

早期レスポンスをしておいたほうが良い
// 早期レスポンス
response('',200)->send();

モーダルからの値を送った後、3秒以内にレスポンスを返さないとエラーが返る仕様になっています。
DB更新処理など少し時間がかかる処理を挟む場合、早期レスポンスでまずダイアログを閉じてしまってから処理を行いましょう。

モーダルは色々なtypeで送られてくるのでtypeによる振り分けが必要

モーダルで「登録」を押した時、 type = 'view_submission' でリクエストが飛びます。
しかし、それ以外にもセレクトボックスを更新した場合も type = 'block_actions' でリクエストが飛びます。
https://api.slack.com/surfaces/modals/using#response_actions

そのため、typeによってうまくハンドリングしないとエラーになってしまうのでそこんとこうまく書きましょう。

モーダルの処理が完了した後は完了メッセージはない?

分からなかった点ですが、普通であれば response_url が返ってくるのですが、モーダルの場合は response_url が返ってこなかったので完了メッセージを送ることが出来ませんでした(詳しい方教えて下さい)
完了メッセージがないのは気持ち悪いので、今回は chat.postEphemeral を使ってレスポンスを返しました。

$url = 'https://slack.com/api/chat.postEphemeral';

積極的に綺麗なモーダルを作って行こうな

以前は dialog.open というAPIを使ってダイアログを表示するのが主流でしたが、新しい機能として modal が作られ、まだまだ参考資料が少ない状態です。
複数モーダルに渡るパラメータの入力なども可能なので、今回の記事は本当に基礎の基礎のような記事です。
この記事を参考にもっと色々な使い方が増えていってほしいと思います。

Twitter もやっているので、なにかありましたらフォロー&アドバイス頂けると嬉しいです

ここまで読んで頂きありがとうございました〜〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】Azure Blob Storageを使ってみる

AWSが大人気ですが、Azureも世界で見れば大人気です。

機会があってAzureを使うことになったので、記事を投下していきます。

Azureの良いところは

○管理画面見やすい

○スタートアップ支援に力を入れてる
https://www.microsoft.com/ja-jp/biz/startups/newspicks-20190819.aspx

だと思います。

早速本題に行きます!

ドキュメント

https://docs.microsoft.com/ja-jp/azure/storage/blobs/

AWSもそうですが、ドキュメント読むの大変です。

サンプルURL

https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-quickstart-blobs-php?tabs=linux

該当する場所を探すのが大変だと思うので先に貼っときます。

パッケージのインストール

https://github.com/Azure/azure-storage-php

composer.json
"require": {
"microsoft/azure-storage-blob": "*"
}
ターミナル.
composer install

.envに記載

Azureでストレージアカウントの作成→左のメニューからアクセスキー

スクリーンショット 2020-04-05 22.46.56.png

ストレージアカウント名と、キーを使います。

env.
AZURE_BLOB_ACCOUNT_NAME=こぴぺしたストレージアカウント名をここに
AZURE_BLOB_ACCOUNT_KEY=こぴぺしたkeyをここに。

configディレクトリでazure.phpというファイルを作ります。

azure.php
  'account_name' => env('AZURE_BLOB_ACCOUNT_NAME'),
  'account_key' => env('AZURE_BLOB_ACCOUNT_KEY'),

としておきます。

保存

TestController.php
//これ使いました。
use Illuminate\Http\Request;
use Auth;
use Illuminate\Support\Str;

//AzureBlobのパッケージ
use MicrosoftAzure\Storage\Blob\BlobRestProxy;
use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
use MicrosoftAzure\Storage\Blob\Models\ListBlobsOptions;
use MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions;
use MicrosoftAzure\Storage\Blob\Models\PublicAccessType;

class UploaderController extends Controller {

public function uploadImage(Request $request)
    {
        //.envのアクセスキーを呼び出す
        $connectionString = "DefaultEndpointsProtocol=https;AccountName=".config('azure.account_name').";AccountKey=".config('azure.account_key');
        //おまじない
        $blobClient = BlobRestProxy::createBlobService($connectionString);

        //inputでファイルが送られてきてます
        $image = $request->file('image');

        //もしイメージがあれば
        if (!empty($image)) {
            //送られてきた画像を読み込む
            $content = fopen($image, "r");
            //コンテナ名
            $containerName = 'test';
            //アップロード先はは「/」で階層を指定できる
            $upload_path = Auth::id().'/image/';
       //ファイル名
            $file_name = Str::random(10).'.jpg';
            //ここで保存(コンテナ名、ファイル名、ファイル)
            $blobClient->createBlockBlob($containerName,$upload_path.$file_name, $content); 
         }  else {
            //エラー
         }
    }
}

AWSと違うのは、「コンテナ」というのがあるところだと思います。
コンテナは公式のGUIで操作して作成することもできますが、コードでも作れます。

   $blobClient->createContainer($containerName, $createContainerOptions);
    //オプション
    $createContainerOptions = new CreateContainerOptions();
    //コンテナ、BLOB両方ともパブリックを与えてる
    $createContainerOptions->setPublicAccess(PublicAccessType::CONTAINER_AND_BLOBS);
    // メタデータを与えられる
    $createContainerOptions->addMetaData("key1", "value1");
    $createContainerOptions->addMetaData("key2", "value2");
   //コンテナ名
    $containerName = 'test';
    //コンテナ作成
    $blobClient->createContainer($containerName, $createContainerOptions);

これでコンテナを作成できます。

注意点は

「既に存在するコンテナ名で作成しようとするとエラー」になります

自分はコンテナはポータルサイト上で作成しておいて、そのコンテナ上にアップするような使い方をしています。

消す

TestController.php
$blobClient = BlobRestProxy::createBlobService($connectionString);
//コンテナとファイル名
$blobClient->deleteBlob($container, $upload_path.$file_name);

これだけで消せます。

保存先を取得して消す

TestContoller.php
$blobClient = BlobRestProxy::createBlobService($connectionString);
//リストで取得する
$listBlobsOptions = new ListBlobsOptions();
//オプションでファイルの階層を指定
$uploa_path = Auth::id().'/image'
$listBlobsOptions->setPrefix($upload_path);
//resultに結果が全て入ってくる
$result = $blobClient->listBlobs($container, $listBlobsOptions);
foreach ($result->getBlobs() as $blob) {
   //urlの取得
   $url = $blob->getUrl();
   //例えばこのリスト全部消すなら
   //コンテナファイルの場所取得
   $delete_url = Str::after($url, $container.'/');
   //消す
   $blobClient->deleteBlob($container, $delete_url);
}

コンテナを消すメソッドはあるがディレクトリを消す方法がわからなかった(涙)

ストリーミングの動画のファイルを全て消したいときにこのように書きました。

多分ディレクトリで消せないようになっているのではと推測しています(知ってる方いれば教えてください)

まとめ

LaravelというよりはPHP。

S3より行数は多いけど、ビビる必要なし!

MicrosoftはGithubやVisual Studio Onlineなどとの連携で楽しいことしてくれそうな気がします!

ご静聴ありがとうございました!

参考文献

https://www.microsoft.com/ja-jp/biz/startups/newspicks-20190819.aspx
https://docs.microsoft.com/ja-jp/azure/storage/blobs/
https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-quickstart-blobs-php?tabs=linux

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel入門2版(本)が全然始められない人のためのまとめ

吐きそうになりながらlaravelインストールした話

ララベルの代表書であるララベル入門第二版を購入してインストールしようとしたがつまずくポイントが多すぎて吐きそうになったので過去の自分を助けてあげるつもりで解決策を書いていこうと思います。

環境/対象者

mac Os catalina
これからlaravel6とphp7.2を使おうとしている人
terminalのコマンドがある程度(directoryの移動程度)ができる人

詰みポイントのまとめ

  • まずこれが設定できていないと詰む zshとbash
  • composerでlaravelをインストールしようとしてもphpのバージョンがふるかったり相性が合わないと詰む
  • pathの通しかたが分からなくて詰む、というかパスが何か分からなくて詰む

ますこれができていないと詰むzashとbash

まずlaravelを初めてインストールしようとした時にterminalのshellがzshだとパスがうまく通せなくて詰みます。
bashに変更しましょう。

echo $SHELL

でshellがbashになっているか確認しましょう。

bin/bash

の表示が出ればbashになっているのでOKです。
もしbashになっていなかったらshellスクリプトの変えかた でググればすぐでてくるので検索してみてください。

composerでlaravelをインストールしようとしてもphpのバージョンがふるかったり相性が合わないと詰む

さてまずはcomposerのインストールの方法ですが
composer公式サイト(getcomposer.org)でcomposer.pharをダウンロードしてきてください。
ダウンロードした後は、composer.pharを

sudo mv composer.phar /usr/local/bin/composer

でbinディレクトリーに移動させた後に

chamod a+x /usr/local/bin/composer

でパーミッションを変更してあげてください。
ここまできたら

composer global require laravel/installer

でララベルのインストールをすることになるのですが、おそらくできないと思います。

- 原因

Installation request for laravel/installer ^2.1 -> satisfiable by laravel/installer[v2.1.0].
laravel/installer v2.1.0 requires ext-zip * -> the requested PHP extension zip is missing from your system.

多分こんなかんじのエラーが出てくると思いますが、ざっくり説明すると、ext-zipっていうphpのファイルがないよっていってます。

  • 解決策

調べていたら、yumでphpのたりないファイルをインストールする方法が書いていたのですが、macでyumを使おうとするとめんどくさそうだったのでhomebrewを使って、ext-zipをインストールします。

brew update
brew install php@7.4
brew link php@7.4

上のコードを打つとphpのファイルがインストールされるのでひとまずララベル自体をインストールすることはできるます。

pathの通しかたが分からなくて詰む、というかパスが何か分からなくて詰む

最後に pathの通しかたが分からなくて詰む、というかパスが何か分からなくて詰む、ですが、
ますはpathとは何かというのをざっくり説明します。

pathを通すというのは、terminal上で「laravel」という文言を使えるようにすることです。
pathが通っていないと

laravel:command not found

とでてきてコマンド使えなくて作業できません。

pathは
.bash_profileというファイルに直接書き込まなければいけないので、ますはホームディレクトリに移動してください。その後に

$ ls -a
$ cd .bash_profile

で隠しファイルの.bash_profileが存在することを確認してから.bash_profileに移動してください。
次に

$ vim ~/.bash_profile

でvimを起動して.bash_profileを編集していきます。
vimの操作は他にいい記事がたくさんあるので検索してください。
vimで開いた後は.bash_profileの最後尾に

export PATH=$HOME/.composer/vendor/bin:$PATH

を追加して保存した上で終了してください。
最後に

$ source ~/.bash_profile

を入力することで変更を保存します。

$ laravel -V

でlaravelコマンドが使えることを確認すればひとまず完了です。

まとめ

本を買ったはいいけどlaravelがインストールできなくてくるしんでる人の助けになれば嬉しいです。
他に不明点や間違いがあればコメントにてご指摘お願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む