20211202のlaravelに関する記事は14件です。

Laravel8 AWS EC2デプロイ①

この記事では、laravelで開発したポートフォリオのAWS EC2へのデプロイについて紹介していきます! 記事が長くなりそうなので、細かい説明とは省いてなるべく実行手順のみ記載していくようにします! ポートフォリオ使用技術 フロントエンド:HTML5、CSS、bootstrap4.5.0、Tailwindcss2.2.15 バックエンド:PHP7.4.15、Laravel8.34.0、Jetstream1.0、Livewire インフラ:Docker20.10.2、nginx1.18、MySQL8.0.23/phpMyAdmin、Apache2.4.38、AWS S3 デプロイ環境 デプロイ先:AWS EC2 サーバー:nginx(Apacheの場合も記載しました。) 1.AWS EC2 インスタンス作成 1.AWSからログインしてEC2画面にアクセス。 2.画面右上のリージョンを「東京」に。 3.「インスタンスを起動」をクリック。 4.「AWS Linux2」を選択。 5.無料枠の「t2.micro」を選択。→次のステップでステップ5まで移動。 ※ステップ3、4はデフォルトのまま。 6.「タグを追加」→「キー」と「値」を入力。 7.「ルールの追加」→「HTTP」と「HTTPS」を追加→「確認と作成」 8.「起動」 9.「新しいキーペアの作成」→「キーペア名」入力→「キーペアのダウンロード」でローカルに保存→「インスタンスを作成」 10.作成されたインスタンスにチェック→接続 11.10の接続情報を元にターミナルからリモート接続を実施。 $ cd #ターミナルをスタート地点へ $ mkdir ~/.ssh   #.sshディレクトリを作成 $ mv Downloads/sample-key.pem .ssh/ #mvコマンドで、「キー.pem」を.sshディレクトリに移動 $ cd .ssh/ #.sshにディレクトリ移動 .ssh $ ls #pemファイルが存在するか確認。「sample-key.pem」が存在すればOK .ssh $ chmod 400 sample-key.pem #キーファイル(○○○.pem)のパーミッションを変更 .ssh $ ssh -i "sample-key.pem" ec2-user@ec2-52-68-186-250.ap-northeast-1.compute.amazonaws.com #ログイン(AWS 接続画面記載のコードをコピペ) Last login: Thu Dec 2 06:14:35 2021 from p3014131-ipoe.ipoe.ocn.ne.jp __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ nginxをセットアップ 今回はnginxをセットアップしますが、Apache2を使用したい方はApache2のインストールを参考にしてください。 Apache2の場合 [ec2-user@ip-172-31-45-44 ~]$ sudo yum update #パッケージアップデート 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd amzn2-core | 3.7 kB 00:00:00 No packages marked for update #「No packages marked for update」は、アップデートするパッケージがないということなのでこのままでOK。 $ sudo yum install apache2 ※初めに選択したAMIがAWS Linux2の場合、aptコマンドが使用できない為、apt→yumに変更してコマンド実行。 nginxの場合 #EC2インスタンスは、nginxのyum intstallが有効になっていない為、有効化。 [ec2-user@ip-172-31-45-44 ~]$ sudo amazon-linux-extras enable nginx1 [ec2-user@ip-172-31-45-44 ~]$ sudo yum -y install nginx #インストール [ec2-user@ip-172-31-45-44 ~]$ nginx -v #バージョン確認 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl enable nginx #nginx自動起動化 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl start nginx.service #起動 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl status nginx.service #起動確認 続く AWSインスタンス一覧画面→作成したインスタンスにチェック→画面下のインスタンス情報内のパブリックIPv4アドレスからアクセス→サーバーの初期画面が表示されればインスタンスの作成とサーバーのセットアップが完了です! とりあえずここまでお疲れ様でした! まだ初めの段階ですが、エラーに引っかかってしまうとこれだけの作業でも時間が過ぎてしまいますよね。。 記事が長くなってしまう為、続きはパート2で紹介していきます! 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Docker AWS EC2デプロイ①

この記事では、laravelで開発したポートフォリオのAWS EC2へのデプロイについて紹介していきます! 記事が長くなりそうなので、細かい説明とは省いてなるべく実行手順のみ記載していくようにします! ポートフォリオ使用技術 フロントエンド:HTML5、CSS、bootstrap4.5.0、Tailwindcss2.2.15 バックエンド:PHP7.4.15、Laravel8.34.0、Jetstream1.0、Livewire インフラ:Docker20.10.2、nginx1.18、MySQL8.0.23/phpMyAdmin、Apache2.4.38、AWS S3 デプロイ環境 デプロイ先:AWS EC2 サーバー:nginx(Apacheの場合も記載しました。) 1.AWS EC2 インスタンス作成 1.AWSからログインしてEC2画面にアクセス。 2.画面右上のリージョンを「東京」に。 3.「インスタンスを起動」をクリック。 4.「AWS Linux2」を選択。 5.無料枠の「t2.micro」を選択。→次のステップでステップ5まで移動。 ※ステップ3、4はデフォルトのまま。 6.「タグを追加」→「キー」と「値」を入力。 7.「ルールの追加」→「HTTP」と「HTTPS」を追加→「確認と作成」 8.「起動」 9.「新しいキーペアの作成」→「キーペア名」入力→「キーペアのダウンロード」でローカルに保存→「インスタンスを作成」 10.作成されたインスタンスにチェック→接続 11.10の接続情報を元にターミナルからリモート接続を実施。 $ cd #ターミナルをスタート地点へ $ mkdir ~/.ssh   #.sshディレクトリを作成 $ mv Downloads/sample-key.pem .ssh/ #mvコマンドで、「キー.pem」を.sshディレクトリに移動 $ cd .ssh/ #.sshにディレクトリ移動 .ssh $ ls #pemファイルが存在するか確認。「sample-key.pem」が存在すればOK .ssh $ chmod 400 sample-key.pem #キーファイル(○○○.pem)のパーミッションを変更 .ssh $ ssh -i "sample-key.pem" ec2-user@ec2-52-68-186-250.ap-northeast-1.compute.amazonaws.com #ログイン(AWS 接続画面記載のコードをコピペ) Last login: Thu Dec 2 06:14:35 2021 from p3014131-ipoe.ipoe.ocn.ne.jp __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ nginxをセットアップ 今回はnginxをセットアップしますが、Apache2を使用したい方はApache2のインストールを参考にしてください。 Apache2の場合 [ec2-user@ip-172-31-45-44 ~]$ sudo yum update #パッケージアップデート 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd amzn2-core | 3.7 kB 00:00:00 No packages marked for update #「No packages marked for update」は、アップデートするパッケージがないということなのでこのままでOK。 $ sudo yum install apache2 ※初めに選択したAMIがAWS Linux2の場合、aptコマンドが使用できない為、apt→yumに変更してコマンド実行。 nginxの場合 #EC2インスタンスは、nginxのyum intstallが有効になっていない為、有効化。 [ec2-user@ip-172-31-45-44 ~]$ sudo amazon-linux-extras enable nginx1 [ec2-user@ip-172-31-45-44 ~]$ sudo yum -y install nginx #インストール [ec2-user@ip-172-31-45-44 ~]$ nginx -v #バージョン確認 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl enable nginx #nginx自動起動化 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl start nginx.service #起動 [ec2-user@ip-172-31-45-44 ~]$ sudo systemctl status nginx.service #起動確認 続く AWSインスタンス一覧画面→作成したインスタンスにチェック→画面下のインスタンス情報内のパブリックIPv4アドレスからアクセス→サーバーの初期画面が表示されればインスタンスの作成とサーバーのセットアップが完了です! とりあえずここまでお疲れ様でした! まだ初めの段階ですが、エラーに引っかかってしまうとこれだけの作業でも時間が過ぎてしまいますよね。。 記事が長くなってしまう為、続きはパート2で紹介していきます! 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 8.1 がリリース!だけど思わぬ落とし穴も

PHP 8.1 がリリース! 2021年11月25日に PHP 8.1 がリリースされました enum の追加や readonly プロパティが設定できるなど、嬉しい機能が盛りだくさんですね。 詳しい内容は既に記事がありますので、ぜひそちらをご覧ください(感謝! )。 Laravel の対応は? 普段は Laravel をメインで使っていますので、 PHP 8.1 の恩恵を受けるためには Laravel のバージョンアップをしなければなりません。 Github を見ると、2021/10/22 リリースの v8.67.0 からサポートされているようです。 ただ、依存パッケージが対応しているかなどは調査が必要ですし、リリース済のコードだと尚更気軽にバージョンアップはできないです。 つまりプロジェクトによってはあまり関係ない...そんなふうに考えていた時期が僕にもありました。 一方その頃... それはいつも通りチームメンバーが PHP 8.0 × Laravel v8.33.1 環境で CD/CI を回したときでした。 急に CD/CI が泡を吹いて倒れたのです。 エラーログ Fatal error: During inheritance of ArrayAccess: Uncaught ErrorException: Return type of Illuminate\Support\Collection::offsetExists($key) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in vendor/laravel/framework/src/Illuminate/Collections/Collection.php:1411 みたことないエラーだったので、パッと見は原因がわかりませんでした。 ちょっと前までは元気に動いていたのに一体どうして... ただ、幸いにも原因はすぐに目星がつきました。 原因は composer の docker image このエラーはバックエンドのビルド時に起きたもので、そこでは Docker で composer:2 というイメージを使用していました。 このイメージの中で使用されている PHP のバージョンが 8.1 に上げられたことが原因でした。 イメージを composer:2.1.11 に指定したところ、無事にビルドが通るようになりました。 composer:2.1.12 以降は PHP 8.1 を使うようになっているようなので、しばらくは注意が必要です。 教訓 Docker のイメージはちゃんとマイナーバージョンまで指定した方がいいですね。 あと今回は PHP 8.1 がリリースされたことを知っていたことが大きく、エラーになったタイミングとリリースされた日が近かったので目星がつき、早期の解決につながりました。 自分が使っている技術については最新情報をキャッチアップすることが大事だと改めて認識しました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 可読性の高いコードを書く為のサービス層(app/Serviceフォルダ)の使い方 シンプルに解説!!

はじめに Webアプリの規模が大きくなるにつれ、ファットモデル、ファットコントローラ化が進んでしまい、保守性が低下します。 その様な場合、appフォルダ化にServiceフォルダを作成し、その下にコントローラーやモデルの処理を移していきます。 ※Service層に入れるべき処理やクリーンアーキテクチャに関しては別の方の記事を参照して下さい。 今後は別の記事でサービスプロバイダやファサード、__constructについても解説していきます!!! 目次 Serviceフォルダ作成 クラス名やメソッドを記述 Controllerでサービスクラスを使用する Viewでサービスクラスを使用する 最後に Serviceフォルダ作成 ・appフォルダ下にServiceフォルダを作成します。 ・Serviceフォルダ下にファイルを作成します。今回の場合はCalculation.phpとします。 ※実際にはServiceの下にいくつかフォルダを作成して、その下にファイルを作成する構成となります。 <?php namespace App\Services; class クラス名 { // この中にファットコントローラーの原因になっているメソッドを記載する。 } クラス名やメソッドを記述 こちらは足し算と引き算ができる簡単な処理です。 <?php // Serviceフォルダの下にフォルダを作成している場合、パスを追記してください。今回は特に追加記述なし。 namespace App\Services; // クラス名を追記 class Calculation {        // 足し算のメソッドを追記 public function addition($number) { return $number + 1; }       // 引き算のメソッドを追記 public function subtraction($number) { return $number - 1; } } Controllerでサービスクラスを使用する これで、Serviceフォルダ内のCalculationクラスにあるメソッドを使用する事が出来ます。 //  Controller(どのコントローラーでもいいです・・・) // Calculationクラスのuse宣言 use App\Services\Calculation; public function index() { // クラスのインスタンス化 $calculation = new Calculation;         // Calculationクラスのadditionメソッドで足し算を行う。 // ddの結果 => 2 dd($calculation->addition(1)); // Calculationクラスのsubtractionメソッドで引き算を行う。 // ddの結果 => 0 dd($calculation->subtraction(1)); } Viewでサービスクラスを使用する コントローラーだけでなく、Viewファイルでも呼び出す事ができます。 しかし、これではuse宣言やインスタンス化の処理をいちいちView側に記載しなければならない為、見づらく保守性が悪くなってしまいます。 その為、このuse宣言やインスタンス化をせずに済む方法を次回紹介します!! Viewファイル <?php // use宣言 use App\Services\Calculation; // インスタンス化 $calculation = new Calculation; ?> // 足し算の処理 <div>{{ $calculation::addition(1) }}</div> // 引き算の処理 <div>{{ $calculation::subtraction(1) }}</div> 【以下出力結果】 最後に とりあえず、サービス層の使い方を紹介しました。サービス層のクラスを使う際には何の特別なこともなく、ただクラスを作成して、それを使いたいところで使うだけです。 今後は、冗長になっているインスタンス化部分の解説と、サービスプロバイダー、ファサードの解説もしていきます!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

細かすぎて伝わらないLaravel選手権8(laravel8)

Laraevl選手権8と言っていますが8回もやってません。versionに合わせました。 laravelのchangelogを眺めて、新しく追加された細かい機能を見ていこうぜ!っていうコーナーです 全部を網羅した訳ではなく、Addedされた中でも自分が気になるものをピックアップしました。 paginationにlinksプロパティーが追加 v8.0.3 src/Illuminate/Pagination/LengthAwarePaginator.php こんなふうにpaginateをjsonで返した場合にlinksプロパティーが追加されました。linksプロパティーの詳細は「laravel pagination カスタマイズ」で検索! Route::get('/users', function () { return User::paginate(); }); { "total": 50, "per_page": 15, "current_page": 1, "last_page": 4, "first_page_url": "http://laravel.app?page=1", "last_page_url": "http://laravel.app?page=4", "next_page_url": "http://laravel.app?page=2", "prev_page_url": null, "path": "http://laravel.app", "from": 1, "to": 15, "data":[ { // レコード… }, { // レコード… } ], // ↓追加された "links": [ { "url": null, "label": "&laquo; Previous", "active": false }, { "url": "http://laravel.app?page=1", "label": "1", "active": true }, { "url": null, "label": "Next &raquo;", "active": false } ], } Testクラス内でjson型のカラムと比較できるcastAsJson()メソッドが追加 v8.3.0 src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php $this->assertDatabaseHas('users', [ 'name' => 'Peter Parker', 'email' => 'spidey@yahoo.com', 'skills' => $this->castAsJson(json_encode(['web slinging', 'spidey-sense', 'sticky feet'])), ]); キュー処理のジョブバッチで使用するbatchメソッドにクロージャ(無名関数)を渡せるように v8.3.0 src/Illuminate/Bus/Batch.php Bus::batch([ new ProcessPodcast, function () { // ... }, new ReleasePodcast ])->dispatch(); ジョブをクリアできるphp artisan queue:clearコマンドが追加 v8.4.0 src/Illuminate/Queue/Console/ClearCommand.php ジョブ(jobsテーブル)はクリアできるけど、ジョブバッチ(job_batchesテーブル)には残るので注意です! v8.21.0からは別コマンドでジョブバッチもクリアできます php artisan queue:clear クエリービルダにcrossJoinSub()メソッド追加 v8.5.0 src/Illuminate/Database/Query/Builder.php joinSub、leftJoinSub、rightJoinSubに加えてcrossJoinSubが追加 LazyCollectionにタイムアウトを設定できるように v8.6.0 src/Illuminate/Collections/LazyCollection.php LazyCollectionにタイムアウトを設定できるようになりました。 $lazyCollection ->takeUntilTimeout(now()->add(2, 'minutes')) ->each(fn ($item) => doSomethingThatMayTakeSomeTime($item)); // ^^ This will only process items for up to 2 minutes ^^ Httpクライアントでのレスポンスエラー発生時にonError()でコールバック処理ができるように v8.7.0 src/Illuminate/Http/Client/Response.php throw()との違いは例外を投げるかどうかです。 Before $response = $client->withHeaders($headers)->post($url, $payload); if ($response->failed()) { Log::error('Twitter API failed posting Tweet', [ 'url' => $url, 'payload' => $payload, 'headers' => $headers, 'response' => $response->body(), ]); $response->throw(); } return $response->json(); After return $client->withHeaders($headers) ->post($url, $payload) ->onError(fn ($response) => Log::error('Twitter API failed posting Tweet', [ 'url' => $url, 'payload' => $payload, 'headers' => $headers, 'response' => $response->body(), ]) )->throw()->json(); CollectionにpipeInto()メソッドが追加されました v8.8.0 src/Illuminate/Collections/Traits/EnumeratesValues.php APIリソースを返す時に使えそうです pipeInto class ResourceCollection { /** * コレクションインスタンス */ public $collection; /** * 新しいResourceCollectionインスタンスの生成 * * @param Collection $collection * @return void */ public function __construct(Collection $collection) { $this->collection = $collection; } } $collection = collect([1, 2, 3]); $resource = $collection->pipeInto(ResourceCollection::class); $resource->collection->all(); // [1, 2, 3] HttpクライアントでuserAgentをセットするwithUserAgent()メソッドが追加 v8.8.0 src/Illuminate/Collections/Traits/EnumeratesValues.php 地味だけど便利 Before Http::withHeaders(['User-Agent' => $userAgent])->get($url); After Http::withUserAgent($userAgent)->get($url); スケジュールをローカルで実行できるphp artisan schedule:workが追加 今まではスケジュールを動かすのにschedule:runコマンドをcronに登録しておく必要がありましたが、ローカルからフォアグラウンドで動かしておけるschedule:workが追加されました。 これは結構便利ですね paginatorのアイテムを変換できるthrough()メソッドが追加 v8.9.0 src/Illuminate/Pagination/AbstractPaginator.php 今までは$paginator->getCollection()->transform()なんてしていましたが、その必要も無くなりました! return Inertia::render('Contacts/Index', [ 'contacts' => Contact::paginate()->through(function ($contact) { return [ 'id' => $contact->id, 'name' => $contact->name, 'phone' => $contact->phone, 'city' => $contact->city, 'organization' => optional($contact->organization)->only('name') ]; }), ]); Eloquentやクエリービルダでupsertが使えるように v8.10.0 src/Illuminate/Database/Query/Builder.php MySQLの場合on duplicate key updateを使っており、uniqueかprimary keyが必要なので注意! User::upsert([ ['id' => 1, 'email' => 'taylor@example.com'], ['id' => 2, 'email' => 'dayle@example.com'], ], 'email'); バリデーションで倍数のチェックができるように v8.10.0 src/Illuminate/Validation/Concerns/ValidatesAttributes.php <input type="number" step="0.5" name="foo"> public function rules(): array { return [ 'foo' => [ 'multiple_of:0.5', ] ]; } マイグレーションで外部キー制約のカラム削除が簡単に v8.10.0 src/Illuminate/Database/Schema/Blueprint.php これも地味に便利 Before class AddCategoryIdToPostsTable extends Migration { public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropForeign(['category_id']); $table->dropColumn('category_id'); }); } } After class AddCategoryIdToPostsTable extends Migration { public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropConstrainedForeignId('category_id'); }); } } Eloquentのcastsにencryptedが使えるように v8.12.0 src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php 以前はアクセサやカスタムキャストを作る必要がありましたが、直接指定できるように public $casts = [ 'access_token' => 'encrypted', ]; リレーションのクエリにwithMax()|withMin()|withSum()|withAvg()メソッドが追加 v8.12.0 src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php これは結構便利ですね。ただ発行されるSQLはゴリゴリのサブクエリなので注意 Post::withCount('comments'); Post::withMax('comments', 'created_at'); Post::withMin('comments', 'created_at'); Post::withSum('comments', 'foo'); Post::withAvg('comments', 'foo'); Eloquentやクエリービルダでexplainが使えるように v8.12.0 src/Illuminate/Database/Concerns/ExplainsQueries.php 便利! >>> DB::table('users')->where('name', 'Illia Sakovich')->explain() => Illuminate\Support\Collection {#5348 all: [ {#5342 +"id": 1, +"select_type": "SIMPLE", +"table": "users", +"partitions": null, +"type": "ALL", +"possible_keys": null, +"key": null, +"key_len": null, +"ref": null, +"rows": 9, +"filtered": 11.11111164093, +"Extra": "Using where", }, ], } ルーティングに正規表現メソッドが追加 v8.12.0 src/Illuminate/Routing/RouteRegexConstraintTrait.php whereNumber|whereAlpha|whereAlphaNumeric|whereUuidなどが使えるようです Before Route::get('authors/{author}/{book}')->where(['author' => '[0-9]+', 'book' => '[a-zA-Z]+']); After Route::get('authors/{author}/{book}')->whereNumber('author')->whereString('book'); EloquentのCollectionにloadMax()|loadMin()|loadSum()|loadAvg()メソッド追加。EloquentにloadMax()|loadMin()|loadSum()|loadAvg()|loadMorphMax()|loadMorphMin()|loadMorphSum()|loadMorphAvg()メソッド追加 v8.13.0 src/Illuminate/Database/Eloquent/Collection.php src/Illuminate/Database/Eloquent/Model.php これも便利ですね。ただゴリゴリのサブクエリ(略 //Eloquent/Collection public function loadAggregate($relations, $column, $function = null) {...} public function loadCount($relations) {...} //Just modified. public function loadMax($relations, $column) {...} public function loadMin($relations, $column) {...} public function loadSum($relations, $column) {...} public function loadAvg($relations, $column) {...} //Eloquent/Model public function loadAggregate($relations, $column, $function = null) {...} public function loadCount($relations) {...} //Just modified. public function loadMax($relations, $column) {...} public function loadMin($relations, $column) {...} public function loadSum($relations, $column) {...} public function loadAvg($relations, $column) {...} public function loadMorphAggregate($relation, $relations, $column, $function = null) {...} public function loadMorphCount($relation, $relations) {...} //Just modified. public function loadMorphMax($relation, $relations, $column) {...} public function loadMorphMin($relation, $relations, $column) {...} public function loadMorphSum($relation, $relations, $column) {...} public function loadMorphAvg($relation, $relations, $column) {...} こんな感じで使える $user = User::find(1); $user->loadCount('posts'); $user->loadMax('posts', 'created_at'); Eloquentのcastsencryptedで使用する暗号鍵を設定できるModel::encryptUsing()が追加 v8.14.0 src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php use Illuminate\Database\Eloquent\Model; use Illuminate\Encryption\Encrypter; $databaseEncryptionKey = config('database.encryption_key'); $encrypter = new Encrypter($databaseEncryptionKey); Model::encryptUsing($encrypter); HttpのResponseを返す際に指定のクッキーを無くすwithoutCookie()メソッドが追加 v8.15.0 src/Illuminate/Http/ResponseTrait.php 単純に有効期限切れにする感じですね /** * Expire a cookie when sending the response. * * @param \Symfony\Component\HttpFoundation\Cookie|mixed $cookie * @param string|null $path * @param string|null $domain * @return $this */ public function withoutCookie($cookie, $path = null, $domain = null) { if (is_string($cookie) && function_exists('cookie')) { $cookie = cookie($cookie, null, -2628000, $path, $domain); } $this->headers->setCookie($cookie); return $this; } アップロードファイルのテスト時にexistsと合わせてcontentもチェックできるように v8.15.0 src/Illuminate/Filesystem/FilesystemAdapter.php これも便利 Before Storage::disk('reports')->assertExists('foo.csv'); $this->assertSame('my;csv;content', Storage::disk('reports')->read('foo.csv')); After Storage::disk('reports')->assertExists('foo.csv', 'my;csv;content'); Collectionで複数ソートができるように v8.16.0 src/Illuminate/Collections/Collection.php これはナイス $collection = collect([ ['name' => 'Taylor Otwell', 'age' => 34], ['name' => 'Abigail Otwell', 'age' => 30], ['name' => 'Taylor Otwell', 'age' => 36], ['name' => 'Abigail Otwell', 'age' => 32], ]); $sorted = $collection->sortBy([ ['name', 'asc'], ['age', 'desc'], ]); $sorted->values()->all(); /* [ ['name' => 'Abigail Otwell', 'age' => 32], ['name' => 'Abigail Otwell', 'age' => 30], ['name' => 'Taylor Otwell', 'age' => 36], ['name' => 'Taylor Otwell', 'age' => 34], ] */ DBに接続できるphp artisan dbが追加 v8.16.0 src/Illuminate/Database/Console/DbCommand.php べんり!でもmysql-clientがインストールされている必要があるので注意! factoryで、存在する親モデルのインスタンスを紐付けするサポートが追加 v8.18.0 src/Illuminate/Database/Eloquent/Factories/Factory.php factoryを作成する際にforでは親のfactoryを渡す方法だけでしたが use App\Models\Post; use App\Models\User; $posts = Post::factory() ->count(3) ->for(User::factory()->state([ 'name' => 'Jessica Archer', ])) ->create(); 親のモデルインスタンスを渡して紐付けできるように $user = User::factory()->create(); $posts = Post::factory() ->count(3) ->for($user) ->create(); メール本文の内容をテストするためのメソッドがいくつか追加 v8.18.0 src/Illuminate/Mail/Mailable.php これは積極的に使っていきたい use App\Mail\InvoicePaid; use App\Models\User; public function test_mailable_content() { $user = User::factory()->create(); $mailable = new InvoicePaid($user); $mailable->assertSeeInHtml($user->email); $mailable->assertSeeInHtml('Invoice Paid'); $mailable->assertSeeInText($user->email); $mailable->assertSeeInText('Invoice Paid'); } スケジュール一覧を表示するphp artisan schedule:listが追加 v8.19.0 src/Illuminate/Console/Scheduling/ScheduleListCommand.php ジョブデータを暗号化できるように v8.19.0 src/Illuminate/Contracts/Queue/ShouldBeEncrypted.php jobsテーブルのpayloadを見ると大体の内容がわかってしまうが、ShouldBeEncryptedを実装してあげれば暗号可能に use Illuminate\Contracts\Queue\ShouldBeEncrypted; class VerifyUser implements ShouldQueue, ShouldBeEncrypted { private $user; private $socialSecurityNumber; public function __construct($user, $socialSecurityNumber) { $this->user = $user; $this->socialSecurityNumber = $socialSecurityNumber; } } ジョブバッチをクリアできるphp artisan queue:prune-batchesコマンドが追加 v8.21.0 src/Illuminate/Queue/Console/PruneBatchesCommand.php >>> php artisan queue:prune-batches 199 entries deleted. $schedule->command('queue:prune-batches --hours=48')->daily(); クエリービルダに、レコードが1つだけ存在かつそれを取得するsole()メソッドが追加 v8.23.0 src/Illuminate/Database/Concerns/BuildsQueries.php レコードが存在しない、複数レコードが存在する場合は例外を投げます。 Djangoではget、Railsではsoleやfind_sole_byで存在するそうです $user = User::where('name', 'test1')->sole(); throw_if / throw_unless がデフォルトでRuntimeExceptionを投げるように v8.23.0 src/Illuminate/Support/helpers.php これは、、、 並列テストが可能に v8.25.0 src/Illuminate/Testing/ParallelRunner.php これはありがたい!詳しい使い方はドキュメントをチェック! Listeners, Mailables, NotificationsでShouldBeEncryptedが使えるように v8.25.0 src/Illuminate/Events/CallQueuedListener.php src/Illuminate/Mail/SendQueuedMailable.php src/Illuminate/Notifications/SendQueuedNotifications.php v8.19.0でジョブの内容を暗号化するようにリスナー、メール、通知でも使えるみたいですね ルーティングにmissing()メソッドが追加 v8.26.0 src/Illuminate/Routing/Middleware/SubstituteBindings.php ルートモデルバインディングを使用した際に、該当のデータがない場合にModelNotFoundExceptionが投げられますが、それを任意で処理できるように Route::get('/locations/{location:slug}', [LocationsController::class, 'show']) ->name('locations.view') ->missing(fn($request) => Redirect::route('locations.index', null, 301)); after columnで複数追加できるように v8.27.0 src/Illuminate/Database/Schema/Blueprint.php Schema::table('users', function (Blueprint $table) { $table->after('remember_token', function ($table){ $table->string('card_brand')->nullable(); $table->string('card_last_four', 4)->nullable(); }); }); EloquentのcastにAsArrayObject、AsCollectionが使えるように v8.28.0 src/Illuminate/Database/Eloquent/Casts/AsArrayObject.php src/Illuminate/Database/Eloquent/Casts/AsCollection.php castsにarrayを指定すると、jsonやtext型のフィールドに対して配列形式で保存することが可能ですが、AsArrayObjectやAsCollectionを指定することでObjectやCollectionで扱えるようになりました。詳しくはドキュメントをチェック! <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * キャストする必要のある属性 * * @var array */ protected $casts = [ 'options' => AsArrayObject::class, ]; } バリデーションで最初にエラーが見つかったら即終了するstopOnFirstFailure()メソッドが追加 v8.30.0 src/Illuminate/Foundation/Http/FormRequest.php if ($validator->stopOnFirstFailure()->fails()) { // ... } FluentなjsonのAssertが追加 v8.32.0 src/Illuminate/Testing/Fluent/Assert.php Fluent(メソッドチェーンライク)にjsonのassertができるようになりました。 use Illuminate\Testing\Fluent\Assert; class PodcastsControllerTest extends TestCase { public function test_can_view_podcast() { $this->get('/podcasts/41') ->assertJson(fn (Assert $json) => $json ->has('podcast', fn (Assert $json) => $json ->where('id', $podcast->id) ->where('subject', 'The Laravel Podcast') ->where('description', 'The Laravel Podcast brings you Laravel & PHP development news.') ->has('seasons', 4) ->has('seasons.4.episodes', 21) ->has('host', fn (Assert $json) => $json ->where('id', 1) ->where('name', 'Matt Stauffer') ) ->has('subscribers', 7, fn (Assert $json) => $json ->where('id', 2) ->where('name', 'Claudio Dekker') ->where('platform', 'Apple Podcasts') ->etc() ->missing('email') ->missing('password') ) ) ); } } Eloquentにlazy()とlazyById()メソッドが追加 v8.34.0 src/Illuminate/Database/Concerns/BuildsQueries.php lazyを使うことで、LazyCollectionが返ってくるのでメモリ消費を抑えつつ、Collectionのように扱えるようになった!という感じですね $lazyCollection = User::lazy(); MySQLのdatetime型へのuseCurrentOnUpdateをサポート v8.36.0 src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php 無名クラスでマイグレーションが可能に v8.37.0 src/Illuminate/Database/Migrations/Migrator.php クラス名の衝突がなくなりますね <?php use Illuminate\Database\Migrations\Migration; return new class extends Migration { // }; Httpクライアントで同時非同期リクエスト処理ができるように v8.37.0 src/Illuminate/Http/Client/PendingRequest.php src/Illuminate/Http/Client/Pool.php これもかなり便利! use Illuminate\Http\Client\Pool; use Illuminate\Support\Facades\Http; $responses = Http::pool(fn (Pool $pool) => [ $pool->get('http://localhost/first'), $pool->get('http://localhost/second'), $pool->get('http://localhost/third'), ]); return $responses[0]->ok() && $responses[1]->ok() && $responses[2]->ok(); Stringable::whenNotEmpty()が追加 v8.39.0 src/Illuminate/Support/Stringable.php これは汎用性高そう! Str::of(env('SCOUT_PREFIX', '')) ->whenNotEmpty(fn (Stringable $prefix) => $prefix->finish('_')); バリデーションにPasswordルールが追加 v8.39.0 src/Illuminate/Validation/Rules/Password.php こんな感じで使えて $request->validate([ // Makes the password require at least one uppercase and one lowercase letter. 'password' => ['required', 'confirmed', Password::min(8)->mixedCase()], // Makes the password require at least one letter. 'password' => ['required', 'confirmed', Password::min(8)->letters()], // Makes the password require at least one number. 'password' => ['required', 'confirmed', Password::min(8)->numbers()], // Makes the password require at least one symbol. 'password' => ['required', 'confirmed', Password::min(8)->symbols()], // Ensures the password has not been compromised in data leaks. 'password' => ['required', 'confirmed', Password::min(8)->uncompromised()], ]); 全部を組み合わせることも可能 public function store(Request $request) { $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => ['required', 'confirmed', Password::min(8) ->mixedCase() ->letters() ->numbers() ->symbols() ->uncompromised(), ], ]); Modelのイベントを発生せずに更新するメソッドが追加 v8.41.0 src/Illuminate/Database/Eloquent/Model.php update([])と同じように使えます Model::updateQuietly([]) ちなみにsaveメソッドにはすでにあります $user = User::findOrFail(1); $user->name = 'Victoria Faith'; $user->saveQuietly(); カーソルページネーションが追加 v8.41.0 src/Illuminate/Contracts/Pagination/CursorPaginator.php 無限スクロールや、ビッグデータを扱う際のページング時に使うといいらしい 詳しくはドキュメントをチェック! $users = DB::table('users')->orderBy('id')->cursorPaginate(15); おわりに 全部は見切れませんでした!すみません! changelogは議論も含め結構おもしろいので、Laravelっ子はぜひ見てみてください collect()->containsOneItem()のくだりはさすがに笑った 認識間違っている場合はコメントくださると! 次は 「LaravelのOSS動向について書きます」by @hiro5963 さん
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Viewがない場合のLaravelのデバッグ(ロギング)

API化したコントローラーなどViewのない場合は, var_dump() や dd() といった関数が使えない この場合のデバッグの方法はいくつかあるが,手っ取り早くロギング(ログに書き込む)しても大丈夫 LogはLaravelフレームワークの一機能であるため使用する場合は下記を追加し呼び出せるようにする use Illuminate\Support\Facades\Log; あとは下記の通り調べたい変数などを記載 Log::debug($変数); ログの場所 /storage/logs/laravel.log (デフォルト設定の場合) (出力先の変更はconfig/logging.phpを書き換え) ターミナルにログを自動出力できるようにする $ tail -f storage/logs/laravel.log ちろんPostmanとか使い勝手の良いテストツールはあるけどね
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel プロジェクト立ち上げ後最初にやること

内容 Laravelでプロジェクトを立ち上げた時、最初に設定する内容。 目次 タイムゾーン・言語設定 データベースの文字コード デバッグバー データベース設定 メッセージの日本語化 タイムゾーン・言語設定 config/app.php ファイル 'timezone' => 'Asia/Tokyo', 'locale' => 'ja', 'faker_locale' => 'ja_JP', データベースの文字コード config/database.php 'mysql' => [ ・ ・ 'charset' => 'utf8', // 絵文字を使用しない場合 'collation' => 'utf8_unicode_ci', // 絵文字を使用しない場合 ・ ・ ], デバッグバー ブラウザ上にエラーなど出力でき、非常に便利。 ※ 注意点)本番環境ではデバッグバーを表示すると実際のデータベースのやりとりが見えるので、NG! プロジェクトのディレクトリで # インストール composer require barryvdh/laravel-debugbar # サーバー再起動 php artisan serve プロジェクト直下 .env ファイル APP_DEBUG=false or true // true or false で切り替え // 切り替えるたびに簡易サーバー再起動をかける 補足)デバッグバーが消えない!! Laravelにキャッシュを保存する機能があり、それによりfalseにしてもデバッグバーの表示が残る事がある。 対処法(ターミナルでキャシュをクリア) php artisan cache:clear php artisan config:clear # 上記実行後、サーバー再起動 データベース設定 .env ファイル内をデータベースの設定に合わせて変更 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=DB名 DB_USERNAME=ユーザー名 DB_PASSWORD=パスワード メッセージの日本語化 Laravelの機能で搭載されているバリデーションなど、メッセージはデフォルトで英語。 日本語に変更したい場合は下記の手順で設定する。 ①:https://github.com/minoryorg/laravel-resources-lang-ja/tree/master/resources/lang/ja から4つのファイル(auth.php、pagination.php、passwords.php、validation.php)をダウンロード auth.php pagination.php passwords.php validation.php ②:resources/lang ディレクトリに ja ディレクトリを作成。上記4ファイルをjaディレクトリに配置。 resources/lang/ └─── ja └─── auth.php └─── pagination.php └─── passwords.php └─── validation.php ③:validation.phpの最後の行の'attributes'に下記内容を記述しておく。 この文言がメッセージの中に入っていく。(必要なものがあれば適宜追加) 'attributes' => [ 'name'=>'名前', 'email'=>'メールアドレス', 'password'=>'パスワード', ], ※ 上記手動で行ったが、Laravelリファレンスにあるようにコマンドで作成可能 # プロジェクトディレクトリにて php -r "copy('https://readouble.com/laravel/8.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');" php -f install-ja-lang.php php -r "unlink('install-ja-lang.php');"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel8 プロジェクト立ち上げ(MAMP)

内容 MAMP環境でLaravel8のプロジェクトを立ち上げる 手順 MAMPを起動 MAMPのディレクトリに移動 cd /Application/MAMP/htdocs プロジェクトを立ち上げる composer create-project --prefer-dist laravel/laravel アプリ名 "8.*" composer create-project ・・ composerでプロジェクト作成 --prefer-dist ・・リリース版・安定板をダウンロード laravel/laravel ・・ ベンダー名/パッケージ名 laravelの場合はどちらもlaravel "8.*" ・・バージョン指定。指定しないと最新版がダウンロードされる。 Laravelの起動 cd アプリ名 php artisan serve URL: http://127.0.0.1:8000/ に接続 Laravel8 のトップ画面が表示される MySQLの設定 データベース(MySQL)の作成 URL: http://localhost/MAMP/?language=English ヘッダーの Tools > phpMyAdmin 言語を日本語に 新規作成 ⇒ データベース名 ⇒ 作成 データベース ユーザーの作成 データベース名 ⇒ 特権 ⇒ ユーザーアカウントを追加する ユーザー名:laravel_test_user パスワード : password123 もう一度左の一覧からDB名を選択し、ユーザーが追加されていたらOK LaravelのDB設定 .env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel-test DB_USERNAME=laravel_test_user DB_PASSWORD=password123 確認 プロジェクトのディレクトリで php artisan migrate を実行し、phpMyAdminを確認、テーブルが生成されていたら完了。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PHP] [Laravel] ログ出力

Controller.php use Illuminate\Support\Facades\Log; class Controller { public function index(Request $request) { $message = ''; $context = []; try { // System is unusable. Log::emergency($message, $context); // Action must be taken immediately. Log::alert($message, $context); // Critical conditions. Log::critical($message, $context); // Exceptional occurrences that are not errors. Log::warning($message, $context); // Normal but significant events. Log::notice($message, $context); // Interesting events. Log::info($message, $context); // Detailed debug information. Log::debug($message, $context); // Logs with an arbitrary level. Log::log($message, $context); } catch (\Exception $e) { $context = [ 'error_message' => $e->getMessage(), 'error_detail' => $e, ]; Log::error($message, $context); } } } 参考URL https://readouble.com/laravel/8.x/ja/facades.html https://laravel.com/api/8.x/Illuminate/Log/LogManager.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel公式のLaravel sailで「Laravel」+「phpMyAdmin」をサクッと環境構築

この記事は シーエー・アドバンス Advent Calendar 2021 2日目の記事です。 前回の記事は @toubaruさんの 「macOS Catalina に Frida をインストールする」 でした。 明日の記事は @Jeyさんです。 普段、脆弱性診断のクロール業務をしています。 開発研修として、Laravelでの開発があり、今回はDockerの知識があまりない人でも Laravel公式が出しているsailというものを使って環境構築できるようにまとめてみました。 Laravel Sailでは現時点では未サポートのPhpMyAdminを研修では使ったりもするため(Dockerの知識がちょっと必要)追加で記載しています。 概要 Laravel公式から出ているsailが、最近Dockerの知識がない初心者でも環境構築が楽にできる とLaravelやPHP勉強会で耳にしたので気になったので試してみました。 また、社内研修で素のPHPでサイト作成後、Laravelでのサイト作成もあるため、 今後Dockerの知識がない人でもサクッと簡単に環境構築できるかと思い、試してことをまとめてみました。 動作検証環境 Mac Book Pro16(Intel) OS catalina(バージョン10.15.7) Docker Desktop(バージョン3.5.2) 準備 Docker Desktop導入がまだの人はインストールしてください。 これまでのLaravel導入手段まとめ これまで、Laravel導入手段はLaravel非公式のもので様々な方法がありました。 PHPバージョン8以降から、Laravel公式からLaravel Sailが登場し、手軽にLaradockの環境構築ができるようになりました。 Docker系 Laravel Sail curlコマンドでLaradock環境を構築できる。 PHPのバージョンはデフォルトだと8.0 現在Sailが使用できるPHPバージョンは、 8.1、 8.0 、 7.4の3つ。 curlコマンドにwith -mysql等、引数を追加することでサービスの指定もできる。 指定可能なサービスは下記9つ。 mysql pgsql mariadb redis memcached meilisearch minio selenium mailhog サービス指定しない場合のデフォルトで導入されるサービスは下記5つ mysql redis meilisearch mailhog selenium Laradock Laradock - github 全部入りのLaravel Docker環境 Laravel非公式 設定ファイルをいじることで独自の好きな環境を作れる Vessel PHP バージョンは7.4で止まってそう PHP 7.4 MySQL 5.7 Redis (latest) NodeJS (latest), with NPM, Yarn, & Gulp dockerコマンドやdocker-composeコマンドも使えるけれど、vesselコマンドでも動くらしい。参考:VesselでLaravelのDocker環境をサクッと作る - Qiita記事 docker-laravel ucanさんという方が作成したLaravel開発環境 最低限のLaravel開発環境が作成できる Qiitaに手順の解説あり ローカル系 PHPとComposerをローカルインストール - Laravel日本語ドキュメント Laravel Sailで環境構築 1.Docker Desktop導入が完了したら、ターミナルを開き、作成したい任意の場所に移動します。  (今回はデスクトップに作成します。$の後からコマンド入力してください) Terminal $ cd /Users/[自分のPC名]/Desktop 確認方法: Terminal $ pwd #`pwd`コマンド実施後、下記のように返ってきたらOK。 /Users/[自分のPC名]/Desktop [自分のPC名] Desktop 2.下記curlコマンドを叩く。今回はexample-appという名前で作成してます。 Terminal $ curl -s "https://laravel.build/example-app" | bash 3.example-appに移動し、下記コマンドでSailの開始する Terminal $ cd example-app $ ./vendor/bin/sail up -d 4.Sail開始後、localhostにアクセスし、Laravelの画面が表示されたらLaravel導入成功。 5.下記コマンドで一旦、Sail停止します。 Terminal $ ./vendor/bin/sail stop ※Bashエイリアスの設定 上記コマンドを短縮したい場合は、エイリアス設定しておくとsail up、sail stopとsailコマンドで操作ができる。 Terminal $ alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail' Docker起動の度に、上記エイリアス設定しないとSailコマンドが使えないので注意。 Dockerで永続的にエイリアス設定する方法をご存知の方がいれば、コメントで教えていただけると嬉しいです。 6.初回起動時に.env.exampleファイルが作成されているかと思うので、自分の環境様様に.envとしてコピーします Terminal $ .env.example .env 7.上記⑥でコピーした.envファイルの5行目(APP_URL=)の下にLaravelのポート番号を追記する .env APP_PORT=8777 8.上記手順③、④を再度実施し、Laravel sail起動後、http://localhost:8777/ へアクセスし、Laravelの画面が表示されたら設定完了です。 phpMyAndminを追加する Sailは単なるDockerであるため、Sailに関するほぼすべてを自由にカスタマイズできます。 公式でPhpMyAndminはサポートしてない。 公式に上記の記載があったので、通常のDockerでPhpMyAdminを使用する時と同じ様にdocker-compose.ymlファイルに追記していきます。 Sailを起動している場合、./vendor/bin/sail stopかsail stopで一旦Sailを停止します。 docker-compose.ymlのmysqlの下あたりにPhpMyAdminを追記する。(インデント等も同じになるよう記載してください) docker-compose.yml phpmyadmin: image: phpmyadmin/phpmyadmin links: - mysql:mysql ports: - 8888:80 environment: MYSQL_USERNAME: '${DB_USERNAME}' MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' PMA_HOST: mysql networks: - sail 3.PhpMyAdminでログインする際に、データベースのログイン情報が必要なので、データベース情報を追記します。 .env DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=8888 # []内は自分が作成したデータベース名を記述する DB_DATABASE=[example-app] # []内は自分が作成したデータベースのユーザー名を入力する DB_USERNAME=[username] # []内は自分が作成したUserのパスワード入力する DB_PASSWORD=[password] 4.http://localhost:8888/index.phpにアクセスし、データベースのログイン情報を入力しPhpMyAdminにログインできれば完了です。 最終確認 最後にphpMyAndminとLaravel画面が表示されるか確認し、それぞれのページが表示されれば環境構築終了。 Laravel phpMyAndmin この後のLaravelを使ってのサイト作成は通常のLaravelと基本的には同じです。 BurpSuite等のプロキシツールでLaravelアプリの通信を取得したい場合 上記、Laravelで設定したlocalhostのポート番号8777で通信取得できます。 まとめ Laravel公式がサポートしている範囲内であれば、Sailを使ったLaravelの環境構築を爆速で行えるということが分かりました。 Intel Macを持っている初心者の人であれば、curlコマンドを叩くだけでLaravelの環境構築ができてしまうので Laravelの環境構築でつまずくことは、大分減りそうかな。と思いました。 公式がサポートしていないサービスを使いたい等、自分でSailに追加してオリジナルで環境構築を行う場合は、 .ymlファイルやDB作成時の記載方法等のDocker知識がないと厳しそうかなと感じました。 来年1月にはLTSバージョンが出るらしいので、その時にまた適宜修正したいと考えています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel のアセットコンパイル(npm run dev) 実行時にエラーが発生したら確認するべきこと

npm run dev でエラー起きてますか?辛いですね。 「cross-env not found 」とか「mix not found」などと怒られてしまっている場合、以下の内容をチェックしてみてください。 また、npm install 実行時、npm ci 実行時に「symlinkが作れへん」などと言われる場合も以下の内容をチェックしてみてください。 対象 vagrantを利用し、windowsホストマシン、Linuxゲストマシンの環境でLaravelプロジェクトを開発している人 診断 このケースに該当するかチェックするために、プロジェクトのルートディレクトリで以下のコマンドを打ってみましょう。 node_modules/.bin/が存在しているかのチェック ls -l node_modules/.bin/ .bin ディレクトリが存在していれば、このケースには該当しません。 シンボリックリンクが作成できるかどうかのチェック mkdir tmp touch tmp/text1.txt ln -s tmp/text1.txt textsmlink ls -l シンボリックリンクが作成できれば、このケースには該当しません。 前提となる理解 (1)シンボリックリンクが作成できない問題 npm install 時にsymlink が作成できない という問題があります。 これは、ホストOS windows 、ゲストOS Linux という環境で開発しているとよく発生します。 「npm symlink error」などで検索すると のような「--no-bin-links オプションをつけてnpmコマンドを実行する」こういう対処方法が出てきますが、これは罠です。 ※symlinkが作成できないという問題を解決するためにsymlinkを作成しないという対処をしているに過ぎないので、問題は解決しない (2)npm install --no-bin-links を実行すると何が起こるか? --no-bin-links オプションをつけると、 node_modules/.bin ディレクトリが作成されません。 シンボリックリンクを作成しないためコマンド自体は通るのですが、node_modules/.bin が作成されないため、結果として npm run dev 実行時に、cross-env not found とか、mix not found などの問題が発生します。 で、「cross-env not found」などで検索すると 「cross_env までのパスを通せ」という感じの対処方法が出てきてしまいます。 確かにこれで一応 npm run dev コマンドは通るのですが、 根本原因を解決していない 本番環境とローカル環境で package.json に差分が出てしまう という点でイマイチです。 結論 この問題の根本的な原因は、npmインストール時にシンボリックリンクが張れないことなので、この問題を解決します。 問題解決するための具体的な手段は、利用しているホストOSの種類によって変わってくるので、利用中のOSごとに各自ググりましょう。以下、windows10 の場合の対応手順を示します。 Windows10 Pro の場合 正解はこちらです。 Windows 10の場合、シンボリックリンクを作成する権限はデフォルトではAdministratorグループのみになっています。 「ローカル セキュリティ ポリシー」-「ローカル ポリシー」-「ユーザー権利の割り当て」-「シンボリック リンクの作成」に一般ユーザーのグループ(Users)を追加することで、一般ユーザーでもシンボリックリンクを作成できるようになります。 Windows10 Home の場合 windows10 Home の場合、デフォルト状態では「ローカル セキュリティ ポリシー」が利用できないので、これを利用できるように変更してやる必要があります。 上記参考に「ローカル セキュリティ ポリシー」が利用可能な状態になったら、前述の「Windows10 Pro の場合」の手順を実行します。 備考 composer install 時にも、同様の原因によってインストールが失敗することがあるので、なおさら根本原因を解決しておいたほうがよい。 composer.json に、symlink : true のレポジトリが書いてあったりする場合。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

supervisorとLaravelのQueueを使ってみた

はじめに CYBIRDエンジニア Advent Calendar 7日目担当の @kenta_kitagawa です。 サーバサイドの業務を担当しています。 6日目は @cy_ssssさんによる「Unityにまつわる入社前後の変化」でした。 入社した頃の初心を思い出します。 今回の最終目標 弊社はマスターデータ投入の際に事前検証用のdatabaseを毎回作り、検証作業が終わったら検証用databaseを削除する運用をしています。 上記の処理に時間が掛かるので、トリガーはGUIからの操作で、削除処理はバックグラウンドで行えるようにして複数のデータベースを削除する手間を省きます。 そこで php artisan database:drop {database_name} 上記コマンドをviewから実行し、バックグラウンドで処理できるようにします。 databaseクラスはCommandクラスを継承して実装してます。 やること ・Laravelのキューを使う ・LaravelのキューはDatabaseを使って実装 ・supervisorのインストールと設定 ・supervisorでキューワーカーを起動 ・Controllerからコマンドを実行 環境 ・Vagrant 2.2.16 ・VirtualBox 6.1.22 r144080 ・CentOS Linux release 7.3.1611 導入手順(view、Controllerの導入、実装は割愛) 仮想環境に入ってsupervisorのインストール vagrant ssh sudo yum install supervisor confファイルを作成 sudo vi /etc/supervisord.d/laravel-worker.conf /etc/supervisord.d/laravel-worker.conf [program:laravel-worker] process_name=%(program_name)s_%(process_num)02d # artisanがある階層 command=php /home/hoge/artisan queue:work # ログを吐く階層とファイル名 stdout_logfile=/home/hoge/worker.log # commandを実行するユーザ user=hoge autostart=true autorestart=true numprocs=1 redirect_stderr=true stopwaitsecs=3600 laravel-worker.confを読み込む設定 sudo vi /etc/supervisord.conf /etc/supervisord.conf # 一番下の [include] の部分を変更 files = supervisord.d/*.conf supervisorの起動 sudo service supervisord start sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start laravel-worker:* jobsテーブルの作成 php artisan queue:table php artisan migrate .envファイルに追記 QUEUE_DRIVER=database Controllerの任意のところに下記を記述 $params = [ 'database_name' => $database_name ]; // jobs にレコード挿入 Artisan::queue('database:drop', $params)->onConnection('database'); jobsテーブルにレコードがあるとキューワーカーが自動で処理を実行してくれます。 さいごに 今まで手動で何度もコマンドを叩いていたものをキューを使うことによって一度にたくさん実行してもバックグラウンドでキューワーカが自動で処理してくれるようになりました。 明日のCYBIRDエンジニア Advent Calendar 2021 8日目は、 @yuki_utsumi さんによる「数十TBのデータをGoogleドライブにアップしよう」です。 どんな内容なのかとても気になります! ありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LarastanでLaravelプロジェクトを静的解析しよう!

はじめに Laravel Advent Calendar 2021 2日目の投稿です。 PHPのソースコードの品質管理はどのように実施していますでしょうか。 チームで開発している場合はコーディング規約に従ってコードレビューを実施している場合もあるかと思います。 しかし、コードレビューを人の手で実施している場合は以下のような問題があるかと思います。 人力によるコードレビューのつらみ レビューに時間がかかる 修正コード量が多いと修正差分を見ただけで「うっ・・・」っとなります ルール違反していても見逃してしまう場合がある ルールが増えれば増えるほどチェック漏れのリスクが増加します コードレビューしてくれる人を探さなければならない コードレビューできる人が限られている場合、修正したコードがマージされるまでにかなり時間差が生まれることも コードレビューできない人をできるように育てないといけない 特定のスーパープログラマがレビュアーになっている場合は新しいメンバーに後任を務めてもらえるようにするのは簡単ではありません 差し戻し時にコードレビューする人の主観が入ってしまう場合がある 意見が半々に分かれるような指摘は受け入れられない場合があります そもそものやりたいことって? コードレビュー時は 型がかけているか とか PHPDocがちゃんと書けているか などを1つ1つ血眼でチェックしたいわけではないと思います。 基本的なルールは機械的にチェックしてしまい、コードレビューでは可読性や保守性を高めるにはどうしたらよいかといったコードと向き合う時間をできるだけ多く確保したいですね。 静的解析 静的解析ではプログラムを実行せずともソースコードを解析することで構文のチェックができます。つまり、プログラムを実行する前に、エラーとなりうる実装箇所や非推奨となっている実装箇所を発見することができます。 PHP はスクリプト言語であるため、プログラムを実行するまでそのソースコードが文法上問題ないかがわかりません。場合によっては特殊な条件でしか処理されないような分岐があったとして、その分岐内の処理がテストされないままリリースされてしまった結果、リリース後に不具合が発覚するなどもありえます。そのため、静的解析ツールでソースコード全体を機械的に構文チェックすることが有効です。 PHPStan PHPStan はPHPで有名な静的解析ツールの1つです。 Composerでインストール可能であったり公式のDockerコンテナが存在するなど、手軽に導入できる点が嬉しいです。 また、解析の厳密さを示すレベルを9段階で指定できることから、いきなりすべてのエラーに対応するのが大変な巨大なプロジェクトにも比較的導入しやすいかと思います。 各レベル別の解析内容は公式のドキュメントを参照していただけますと幸いです。 Larastan 前置きが長くなりましたが本題のLarastanについて記述していきます。 Larastan は PHPStanの拡張であり、Laravel プロジェクトの静的解析が可能です。 Larastan では Laravel でアプリケーションを作成する上でパフォーマンスを劣化させる可能性がある実装箇所や実行時エラーになりえる箇所をチェックすることができます。 導入方法 公式のREADMEにもしっかりと記載されていますが改めて解説します。 composer 経由での取得 Laravelプロジェクトのルートに移動して以下コマンドを実行 composer require nunomaduro/larastan --dev 設定ファイルの作成 Laravelプロジェクトのルートにて phpstan.neon または phpstan.neon.dist というファイル名のファイルを作成して以下の内容を記載します。 includes: - ./vendor/nunomaduro/larastan/extension.neon parameters: paths: - app # The level 9 is the highest level level: 5 ignoreErrors: - '#Unsafe usage of new static#' excludePaths: - ./*/*/FileToBeExcluded.php checkMissingIterableValueType: false 各パラメータの詳しい内容は以下をご参照ください。 Larastan による静的解析の実行 以下のコマンドを実行することで Larastan による静的解析が実行できます。 ./vendor/bin/phpstan analyse 解析結果はPHPStanによる実行結果に加えてLarastanで独自拡張された解析ルールで解析された結果が表示されます。 Larastanの解析ルール Larastanによって解析できる特別な解析ルールをいくつかご紹介いたします。 解析ルールの詳細はGitHub上のドキュメントより参照させていただきます。 NoModelMake Modelクラスの静的メソッドmake()を利用している箇所を検知してくれます。 User::make(); ソースコード上、上記ような書き方をしてもエラーにはなりませんが、インスタンスが無駄に2つ生成されてしまいます。 モデルクラスを利用する場合は単純に new でインスタンスを生成した方が効率的という理由から解析対象となっております。 内部実装を知っていなければそれがパフォーマンスを悪化させる原因になっていることに気づけないのでとてもありがたいですね。 NoUnnecessaryCollectionCall Illuminate\Support\Collection とそのサブクラスの組み合わせにおいて、無駄に重いSQLが生成される可能性がある実装箇所を検知してくれます。 // 改善前 User::all()->count(); $user->roles()->pluck('name')->contains('a role name'); // 改善後 User::count(); $user->roles()->where('name', 'a role name')->exists(); こういうことも知っていないとうっかりやってしまいそうですね。 RelationExistenceRule Eloquent 経由でDBアクセスする際、存在しないカラムに対してデータ取得しようとしている場合に検知することができます。 // Userにというカラムが存在しない場合にエラーを検知 \App\User::query()->has('foo'); // 複数カラムに対するデータ取得の場合でもすべてのカラムが存在しているかが検知可能 \App\Post::query()->has('users.transactions.foo'); マイグレーションを行い、DB構造が変わった場合などに特定処理が壊れてしまっていないかなどを簡単に検知できそうです。 CheckDispatchArgumentTypesCompatibleWithClassConstructorRule ジョブのディスパッチ引数の型がジョブクラスのコンストラクターと互換性があるかをチェックします。 class ExampleJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** @var int */ protected $foo; /** @var string */ protected $bar; public function __construct(int $foo, string $bar) { $this->foo = $foo; $this->bar = $bar; } // Rest of the job class } // 引数が足りないパターン ExampleJob::dispatch(1); // 引数の型が一致していないパターン ExampleJob::dispatch('bar', 1); これも嬉しいですね。 バッチ処理は通常の画面操作テストでは確認しづらい部分かと思いますので、単純ミスなどが早期に見つかる仕組みがあるのは心強いです。 おわりに Larastan は比較的簡単に導入できますが、きっちり有益なエラーを検知してくれます。実行時にようやく見つかるような不具合をより早い段階で気づけるようにしておくことで実装時の手戻りも減らせると思います。また、どういうコードが不適切であるかは知らなければ気付けません。コード品質を高めるための前提知識を静的解析経由で知ることができるのも導入のメリットかも知れません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelについて

Laravelとは PHPのフレームワークで、webアプリケーションを制作に用いられる。 1 MVCモデルを活用している。 MVCとはビジネスロジックをModelが担当し、表示などをViewが処理に、全体の制御を Controllerで行う形態いなる。 2パッケージ管理はComposerを行なってくれている。 依存関係などもまとめてインストールしてくれる。 3 Eloquent(エロクアント) ORM  データベスの操作を行なってくれている。 Eloquent Object Relational Mappingの略で、データベースとモデルにリレーションを持たせて、データを柔軟に扱えるようにしたもの。 Laravelのディレクトリ構成 ─── Laravel ├── app ├── bootstrap ├── config ├── database ├── public ├── resources ├── routes ├── storage ├── tests └── vendor App アプリケーションのコアコードを配置されている。ほとんどの全部のクラスは、このディレクトリに設定されている。 bootstrap フレームワークを初期起動処理するapp.phpファイルを設置している。。このディレクトリには、ルートやサービスのキャッシュファイルなど、パフォーマンスを最適化するためのフレームワークで生成されたファイルを含むcacheディレクトリも含む。通常、このディレクトリ内のファイルを変更する必要はない。 config アプリケーションの全設定ファイルを設置している。 database マイグレーションとモデルファクトリ、初期値設定(シーディング)を配置している。 このディレクトリをSQLiteデータベースの設置場所としても利用できます。 public アプリケーションへの全リクエストの入り口となり、オートローディングを設定するindex.phpファイルがある。また、このディレクトリにはアセット(画像、JavaScript、CSSなど)を配置する。 resources Viewと、CSSやJavaScriptなどの未加工のコンパイルされていないアセットを含む。すべての言語ファイルも格納してる。 routes web.php api.php console.php channels.php アプリケーションのすべてのルート定義を配置している。デフォルトでルートファイルをいくつかLaravelは用意されいる。 web.phpファイルは、RouteServiceProviderがwebミドルウェアグループへ配置するルートを記述する。これにより、セッション状態、CSRF保護、およびクッキー暗号化が提供される。アプリケーションがステートレスのRESTful APIを提供しない場合は、すべてのルートがweb.phpファイルで定義される。 api.phpファイルは、RouteServiceProviderがapiミドルウェアグループへ配置するルートを記述しる。これらのルートはステートレスであることが意図されているため、これらのルートを介してアプリケーションに入るリクエストは、トークンを介してで認証されることを意図しており、セッション状態にアクセスできない。 console.phpファイルは、クロージャベースのコンソールコマンドをすべて定義する場所。各クロージャはコマンドインスタンスと結合されるため、各コマンドのIOメソッドを操作する簡単なアプローチが可能。このファイルはHTTPルートを定義しませんが、アプリケーションへのコンソールベースのエントリポイント(ルート)を定義している。 channels.phpファイルは、アプリケーションがサポートするすべてのイベントブロードキャストチャンネルを登録できる場所。 storage app framework logs ディレクトリに分離される。 appディレクトリは、アプリケーションが作成したファイルを保存するために使用できる。 frameworkディレクトリは、フレームワークが作成したファイルとキャッシュを保存するために使用する。 最後に、logsディレクトリにはアプリケーションのログファイルを保存している。 tests 自動テストを設置する。 vendor Composerによる依存パッケージが配置されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む