20211201のlaravelに関する記事は11件です。

laravel8 Storageファサードのドライバの振る舞い

目的 Storage::get()の振る舞いについて若干詰まったので簡単にまとめておく Storageファサードの振る舞い そもそもStorageファサードはdisc()メソッドや.envで指定しない限りconfig/filesystems.phpの'default'で指定されたドライバを参照しにいく。 ここで言うドライバとはローカルとかS3とかの記憶する「場所」の話である。 完全にデフォルトの場合下記のように記載されてlaravelプロダクトのローカルを参照するようになっている。 config/filesystems.php /* |-------------------------------------------------------------------------- | Default Filesystem Disk |-------------------------------------------------------------------------- | | Here you may specify the default filesystem disk that should be used | by the framework. The "local" disk, as well as a variety of cloud | based disks are available to your application. Just store away! | */ 'default' => env('FILESYSTEM_DRIVER', 'local'), 下記の様に.envに記載されている 場合、ドライバはs3が指定されている。 FILESYSTEM_DRIVER=s3 この場合Storageファサードを使った処理はdisk()メソッドで指定しない限りs3を参照して実行される。 なので「殆どのファイルはs3に上げたいけど、ローカルでzipファイルに固めてダウンロードしたい」などのケースでzipをダウンロードする場合下記のように記載する。 Storage::download()を用いる場合(あくまでダウンロード処理の例のみ記載、コチラだけを記載してもzipで固めてダウンロードしてくれない) Storage::disk('local')->download('ファイルパス', 'ファイル名', 'ヘッダー'); response()を用いる場合 response()->download('ファイルパス', 'ファイル名', 'ヘッダー'); // ダウンロード後のファイルを削除してほしい場合、deleteFileAfterSend(true)を呼ぶ response()->download('ファイルパス', 'ファイル名', 'ヘッダー')->deleteFileAfterSend(true); 参考文献 https://readouble.com/laravel/5.8/ja/filesystem.html#storage ディスクインスタンス取得部分 https://stackoverflow.com/questions/44769693/laravel-file-not-found-at-path-but-it-does-exist
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel Storageファサードのドライバの振る舞い

目的 Storage::get()の振る舞いについて若干詰まったので簡単にまとめておく Storageファサードの振る舞い そもそもStorageファサードはdisc()メソッドや.envで指定しない限りconfig/filesystems.phpの'default'で指定されたドライバを参照しにいく。 ここで言うドライバとはローカルとかS3とかの記憶する「場所」の話である。 完全にデフォルトの場合下記のように記載されてlaravelプロダクトのローカルを参照するようになっている。 config/filesystems.php /* |-------------------------------------------------------------------------- | Default Filesystem Disk |-------------------------------------------------------------------------- | | Here you may specify the default filesystem disk that should be used | by the framework. The "local" disk, as well as a variety of cloud | based disks are available to your application. Just store away! | */ 'default' => env('FILESYSTEM_DRIVER', 'local'), 下記の様に.envに記載されている 場合、ドライバはs3が指定されている。 FILESYSTEM_DRIVER=s3 この場合Storageファサードを使った処理はdisk()メソッドで指定しない限りs3を参照して実行される。 なので「殆どのファイルはs3に上げたいけど、ローカルでzipファイルに固めてダウンロードしたい」などのケースでzipをダウンロードする場合下記のように記載する。 Storage::download()を用いる場合(あくまでダウンロード処理の例のみ記載、コチラだけを記載してもzipで固めてダウンロードしてくれない) Storage::disk('local')->download('ファイルパス', 'ファイル名', 'ヘッダー'); response()を用いる場合 response()->download('ファイルパス', 'ファイル名', 'ヘッダー'); // ダウンロード後のファイルを削除してほしい場合、deleteFileAfterSend(true)を呼ぶ response()->download('ファイルパス', 'ファイル名', 'ヘッダー')->deleteFileAfterSend(true); 参考文献 https://readouble.com/laravel/5.8/ja/filesystem.html#storage ディスクインスタンス取得部分
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

既存テーブルにカラムを追加するには

都道府県を選んだときに、選んだ都道府県に応じた市区町村が表示されるような、 都道府県と市区町村の連動をするための、カラム追加を行います。 具体的には、citiesテーブルにprefecture_idを追加します。 php artisan make:migration add_prefecture_id_to_cities_table --table=cities 下記コマンドの()内が、状況に応じて入る値が変化するところです。 php artisan make:migration add_(追加するカラム名)to(追加するテーブル名)_table --table=(紐づけたい既存のテーブル名) ◆注意点◆ コマンド後半部分の、cities_tableの、tableと記載することを忘れてしまいがちなので、 ここは個人的に注意したいと思います。 その後は、php artisan migrateを実行。 最後に、citiesテーブルにprefecture_idが入っているかを確認します。 sqlite> PRAGMA TABLE_INFO('cities'); 0|id|integer|1||1 1|name|varchar|1||0 2|created_at|datetime|0||0 3|updated_at|datetime|0||0 4|prefecture_id|integer|0||0 見事、入っていました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング初学者が「変数って何なの???」を乗り越えた話

この記事は、2021年4月にプログラミングを始めたわたしが 最初にぶつかった壁である「変数って何なの???」をなんとか乗り越えたよ〜という内容です。 初学者の方で、当時のわたしと同じように悩んでおられる方のお役に立てましたら嬉しいです。 ・ ・ ・ ■ 最初の壁 プログラミングって何か楽しそう〜と思い、 「プログラミング言語ってこんなにいっぱいあるんだー」とか「フレームワークって何w」とか、 基礎知識ゼロの状態だったわたしが、アハハウフフな気持ちで最初にさわり始めたのはPHP(Laravel)でした。 おそらく初学者の登竜門(?)であるToDoアプリを作り始めるやいなや ぶつかった最初の壁は、そう、タイトルにも冒頭にも書いたとおり、「変数って何なの???」というやつです。 それはそれはもうめちゃくちゃ検索しました。 変数とは 変数って何 変数とはつまり 変数 わからない 変数 意味 etc... あああああああ〜調べても調べても書いてあることが理解できない〜〜 user.php 'user_id' => $user_id; こんなふうに書かれててもどれが変数でどれがカラムでそれぞれがどういう動きをしているのかさっぱりわからない。 検索して出てくるサイトや記事を読めば、それが親切丁寧に書いてあることだけは理解できても 肝心の「で、変数って何なの???なんで定義してあげないといけないの???」が全く腑に落とせなかったのです。 (ついでに言うと、関数を自分で作るっていうのも意味がわからないぜ!と思ってました。) ■ 定義するっていうのはつまり 段々と、わたしの悩みは「変数って何なの」から「定義するって何!!!!ギャオーー」に変わっていきました。 ここで突然の自己紹介ですが、わたしには現在2歳の息子がいます。 わたしが定義のことでギャオついていた当時、息子はようやくいくつかの単語を喋るか喋らないかぐらいの年頃です。 そんなわたしと息子がYouTubeで色んな動物が出てくる動画を何気なく見ていたときのこと、 息子はとくにゾウさんが大好きだったので、アニメや実写などいくつか動画を見るなかでも、 ゾウさんが出てくるシーンは「どうあん!!(ゾウさん)どうあん!!」と大喜びだったのですが、 そこでわたしはふと疑問に思いました。 アニメのゾウさんと実写のゾウさん、冷静に考えたら全然違うくない??  と。 だって実写のゾウさんは別に水色とかピンク色じゃないし、にっこりした顔でもないし、 大体あの鳴き声ってパオーンっていう表現で合ってる?? なのに息子はアニメのゾウさんを見ても実写のゾウさんを見ても、どうやら同じくゾウさんだと認識してるっぽい。 鼻が長くて耳が大きくてひらひらしてて、ずんぐりむっくりした動物 をゾウだと思ってる。 ・ ・ ・ んん? もしやこれがつまり定義ってことなのでは??そうなのでは??? なんだか雷に打たれたような気持ちになって(というと少し大袈裟なんですが) 試しに息子に、「ボール持ってきて」とお願いしてみると、息子のお気に入りのボールを持ってきてくれました。 そこでようやく、変数もプログラミングもこれと同じことなんじゃないのかと思い始めるのです。 そのときのわたしの頭に浮かんだものをプログラミングのコード風(あくまでも風)に書きおこすとしたらこんな感じ。 my_son.php public function getFavoriteBall() { $おもちゃ箱 = 遊ぶものがたくさん入ってる箱; $ボール = 丸い形をした遊ぶもの; $おかあさん = いつも家にいてご飯をくれるアイツ; if ( $おもちゃ箱 のなかに $ボール があったら ) { $おかあさん に 渡す; } } そう、そうなのです。 プログラミングを始める前からずっと、知らず知らずのうちに、ありとあらゆるものが定義されている世界で生きていたし 自分自身でもいろんなものを定義して生きていたのです。 人生は定義だらけ。 生活するうえで必要なことは定義がなくては会話もままならないでしょう。 「おーい、いつも家にいてわたしのつくったごはんを食べる小さいひと〜、 あそこの四角い形のやつのなかに入っていて、あなたがよくあそんでいる丸い形のあそぶものを取ってきて」 なんてことになります。超面倒くさいです。 なるほど。定義、大事。 さてさて、こういったことをプログラミング上ではこちらの意図を伝える相手が人間ではなく機械なので、 察してもらうということができません。 仮に、「ねえねえ、アレ取ってきてくれない?」を人間とロボットの間で実現するためには、 - 「ねえねえ」という音を検知したら、ねえねえの後に続く指示を実行するとあらかじめ決めておく - 「アレ」とは何を指すのかをあらかじめ決めておく - 「取ってきてくれない?」で、どこから取ってきて、取ってきたものをどうしなければならないのかをあらかじめ決めておく このあたりを明確にしておく必要があります。 この「あらかじめ決めておく」がつまり、「定義する」ということです。 ■ 「定義する」はOK分かった、じゃあ変数は? 「ねえねえ、アレ取ってきてくれない?」を実現するために必要なことは上記で述べましたが、 「アレ取ってきてくれない?」以外にもロボットにお願いしたいことって色々あると思います。 「ねえねえ、エアコンつけて」 「ねえねえ、部屋の掃除して」 「ねえねえ、最新のヒット曲を再生して」などなど。 エアコンをつけるとは何か、部屋とは何か、掃除とは何か、最新とはいつからいつまでのことを指すのか、 そういった細かいことについてももちろん定義する必要がありますが、 それはそうと、 さきほど追加で挙げた例のためだけに、全く同じ「ねえねえ」を3回も書いてしまいました。 「ねえねえ」を「あのさぁ」に変更したくなったら、また「あのさぁ」を同じ回数書かなければなりませんよね。 正直面倒くさいし、 「ねえねえ」を「ねーねー」と書き間違えた箇所があったら、ロボットさんは厳密に指示された通り動きますから その書き間違えてしまった箇所は「ねえねえ」では動いてくれないので、意図どおり指示が通らなくなってしまいます。 長くなりましたが、ようやくここで変数の登場です。 どのように呼びかけるかについてを変数として定義しちゃえばいいんですよ。 PHP(Laravel)では変数の頭にドルマーク($)をつける決まり事がありまして、それに従って $呼びかけ  という変数を定義します。 hey.php $呼びかけ = ねえねえ; 「$呼びかけ、エアコンつけて」; 「$呼びかけ、部屋の掃除して」; 「$呼びかけ、最新のヒット曲を再生して」; という記述にしておけば、「ねえねえ」を「あのさぁ」に変更したくなっても、 hey.php $呼びかけ = あのさぁ; 「$呼びかけ、エアコンつけて」; 「$呼びかけ、部屋の掃除して」; 「$呼びかけ、最新のヒット曲を再生して」; このように、最初の1行だけ変更すれば済むため非常に効率が良く、書き間違い防止にもなります。 (注:ここではひとまず変数という概念を理解しやすいように日本語表記でコードっぽく書いていますが、実際には上記のように日本語表記では動きません) プログラミングにおいて変数や関数をどういう名前で定義するか、 それには、命名規則(名付けるための決まり事)が大切なようです。 たとえば、少し前にさかのぼって、2歳の息子とボールのくだりあたりで getFavoriteBall という名前の関数っぽいものを書きましたが、 ここに含まれる単語3つ get favorite ball の区切りをどう表記するかの決まり事です。 getFavoriteBall  単語の頭文字をそれぞれ大文字にする:キャメルケースと言います get_favorite_ball  単語の間を _ (アンダースコア)で繋ぐ:スネークケースと言います get-favorite-ball  単語の間を - (ハイフン)で繋ぐ:ケバブケースと言います ※その他及び詳細についてはここでは割愛します。検索してみると色々とわかりやすい記事がたくさんありますのでぜひご覧になってみてください。 命名規則には守らなければならないレベルがいくつかあって、 そのプログラミング言語での決まり事(守らないと大概エラーになる) 複数人でプロジェクトに携わる場合における、プロジェクト内での決まり事 (守らなくてもエラーは出ないかもしれないが可読性や保守性が低下し将来的にエラーを誘発する素因となりえる) 守らなければそもそもプログラムが動いてくれない、というレベルの決まり事と、 守らなくてもプログラムは動くけれども守った方が良い、というレベルの決まり事などがあります。 何かのプロジェクトに途中から参加する場合は 既存の記述がどのように命名されているかを見て、それに従っていけばきっとOKです。 自分1人でプログラミングする場合は、数ヶ月後に読み返してもそのコードを読み解けるかどうか?と考えて頂ければOKです。 このあたりの決まり事を守ったうえで、かつ、できるだけ誰が見ても分かりやすいように、を心がければ 変数の名前も、定数の名前も、関数の名前も、自由で良いと思います。 (注:PHP・Laravelを学習している上での所感です。ほかの言語では違うよ〜ということがあればぜひ教えてください。) とりあえず、まずは「ふーん、命名規則っていうのがあるんやな」ということを心に留めておいておけたら良いのではないでしょうか。 ■ 結論:変数とは 人間がプログラミング言語を用いてパソコンや機械に対して意図や指示を伝えるために、 「これはこういうことです」とするうえで無くてはならないものです。 今では、変数を定義しなかったらどうやってコードを書けばいいのか分からないとさえ感じます。 この結論に至るまでの道のりを今回は記事にしました。 長々とお読み頂きありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 7.* にbootstrapを導入する方法

Laravelにbootstapを導入する方法 まずは、自分の環境を確認する。 qiita.rb $ composer -v Composer version 2.1.11 2021-11-02 12:10:25 $ php artisan --v Laravel Framework 7.30.5 環境を確認できたら、実際にLaravelを組み込みましょう。 Laravel6~からbootstrapが使えなくなったので、自身で使えるようにしないといけません。 まずは以下のコードをターミナル上でコマンドしてみましょう。 qiita.rb $ composer require laravel/ui おそらくエラーが起きるのではないかと思います。 バージョンを指定して、インストールする必要があります。 私はLaravel7.30.5ですので、2系にあたります。 qiita.rb ///1系 $ composer require laravel/ui:1.* ///2系 $ composer require laravel/ui:2.* ///3系 $ composer require laravel/ui:3.* 実行した後は出力結果にある指示に従っていくだけです。 qiita.rb $ php artisan ui bootstrap Bootstrap scaffolding installed successfully. Please run "npm install && npm run dev" to compile your fresh scaffolding. ありがとうございました。参考にしていただけたら幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel BreezeでVue2を使うまでの話

今年初開催のビットスター Advent Calendar 2021 1日目です。 明日は@kansaizineさんのさくらのクラウドで出来るだけ安価にバックアップサーバを運用する工夫です。 はじめに 認証やフロントエンドのセットアップなどするためlaravel uiなどをいままで使用していたのですが、laravel8からはLaravel BreezeとLaravel Jetstreamが推奨されており、現状最新バージョンでVue.jsを指定してインストールコマンドを実行するとVue3がデフォルトで入ってきます。 ただほかのライブラリなどがまだVue3に対応していないなど様々な理由でVue2で開発せざる得ないなど理由がある場合にどうしたかを備忘録的に書いていきます。 ちなみにBreezeは最初からVue3で作成されており、Jetstreamはv2.2からVue3に対応したようでJetstream v2.2を入れるという手もあると思いますが、依存関係で引っかかってしまうので下記に書いていくやり方がいいかと思います。 環境 PHP v8.0.13 Laravel v8.74.0 内容 Breezeのインストール composer require laravel/breeze --dev php artisan breeze:install vue npm run dev ドキュメントを参考にLaravel Breezeをインストールし、Vue.jsでインストールを実行します。 この段階ではVue3になっています。 vue2_install npm uninstall @inertiajs/inertia-vue3 --save-dev npm install vue@"^2.6.0" --save-dev npm install @inertiajs/inertia-vue --save-dev npm install vue-template-compiler --save-dev npm install portal-vue --save-dev npm install vue-loader@"^15.9.8" --save-dev Vue2用にパッケージを入れ替えます。 こちらを参考にしています。 上記を参考にresources/js/app.jsを書き換える 各コンポーネント差分 -import { Link } from '@inertiajs/inertia-vue3'; +import { Link } from '@inertiajs/inertia-vue'; inertia-vue3を削除したので、各コンポーネントでを呼び出している箇所をinertia-vueに変更します。 この状態でnpm run devを実行するとルートエレメントが複数あるとエラーが発生するので各ページ下記のような修正をします。 差分 diff --git a/resources/js/Pages/Welcome.vue b/resources/js/Pages/Welcome.vue index 33dbf28..8c04ad5 100644 --- a/resources/js/Pages/Welcome.vue +++ b/resources/js/Pages/Welcome.vue @@ -1,4 +1,5 @@ <template> +<div> <Head title="Welcome" /> <div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0"> @@ -110,6 +111,7 @@ </div> </div> </div> +</div> </template> <style scoped> 最後にnpm run devでエラーが発生しなければ大丈夫かと思います。 package.json 参考までにpackage.jsonを下記に記載しておきます。 package.json { "private": true, "scripts": { "dev": "npm run development", "development": "mix", "watch": "mix watch", "watch-poll": "mix watch -- --watch-options-poll=1000", "hot": "mix watch --hot", "prod": "npm run production", "production": "mix --production" }, "devDependencies": { "@inertiajs/inertia": "^0.10.0", "@inertiajs/inertia-vue": "^0.7.2", "@inertiajs/progress": "^0.2.6", "@tailwindcss/forms": "^0.2.1", "@vue/compiler-sfc": "^3.0.5", "autoprefixer": "^10.2.4", "axios": "^0.21", "laravel-mix": "^6.0.6", "lodash": "^4.17.19", "portal-vue": "^2.1.7", "postcss": "^8.2.13", "postcss-import": "^14.0.1", "tailwindcss": "^2.1.2", "vue": "^2.6.14", "vue-loader": "^15.9.8", "vue-template-compiler": "^2.6.14" } } 最後に まだVue2で開発する必要があって、調べても海外のフォーラムでざっくりとしか書いておらず微妙に詰まったので備忘録的に残しておきました。 BreezeやJetstreamでVue2でもインストールできるオプションがあればうれしいのですが需要ないんでしょうか。時期が悪いというか時が解決するような気もしますが...
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

techpitのlaravel講座の手順通りにやっていたらTarget class [UserController] does not exist.が出た件

techpitのlaravel講座をやっていたら とあった。 しかし、ユーザーコントローラーファイルはちゃんとあるし、クラスもある 講座通り進めていたが、誤字などがあると思ったので、今度は講座のコードを完全コピペで試してみた はい、ダメでした 原因 私のlaravelのバージョンが8で、講座で使用しているlaravelのバージョンが6だった laravel8とlaravel6では、ルーティングの仕様が変わって違うことが判明(正確には8から変更) laravel7までのルーティング web.php Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () { Route::get('show/{id}', 'UserController@show')->name('users.show'); }); laravel8までのルーティング仕様に変更 web.php Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () { Route::get('show/{id}', [UserController::class, 'show'])->name('users.show'); }); これで、UserControlerのクラスであるshowを参照しますという意味になる しかし、これでも足りないみたいで以下の記述が必要になる web.php use App\Http\Controllers\UserController; //追記 Route::group(['prefix' => 'users', 'middleware' => 'auth'], function () { Route::get('show/{id}', [UserController::class, 'show'])->name('users.show'); }); これでユーザーコントローラーファイルを使いますよという意味になる。 これで、ルーティング通りにshow/{id}にアクセスすると 感想 laravelの仕様変更が原因とは思いもつかなかった laravel8でlaravel7以前の教材や動画を学習している場合気を付けなければいけないと感じた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel de Lambda

PHP Laravelをサーバーレス化する方法として、AWS SAMを使用した手順はAmazon Web Services ブログで公開されています。 今回はコンテナイメージ化することで、より簡単にAWS Lambda上で動かす手順を記載します。 前提 PHPをサーバーレス化するための必須ライブラリ bref 拡張機能 brefphp/extra-php-extensions Laravel用Package brefphp/laravel-bridge Laravelのセットアップ Laravelインストーラー composer global require laravel/installer プロジェクト作成 laravel new laravel-function ログ出力先として標準出力の追加 config/logging.php ... 'channels' => [ ... 'stdout' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => StreamHandler::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'stream' => 'php://stdout', ], ], ], ... 必須ライブラリの追加 bref composer require bref/laravel-bridge --update-with-dependencies worker.phpの作成 SQSからイベントメッセージを受信するためのエントリーポイントを作成 php artisan vendor:publish --tag=serverless-worker aws composer require aws/aws-sdk-php-laravel composer require aws/aws-sdk-php config/aws.phpの作成 php artisan vendor:publish --provider="Aws\Laravel\AwsServiceProvider" AWS用プロバイダ設定追加 config/app.php 'providers' => [ ... Aws\Laravel\AwsServiceProvider::class, ... ], 'aliases' => [ ... 'AWS' => Aws\Laravel\AwsFacade::class, ] Credentials defaultの認証情報を利用するため、不要な設定は削除 config/queue.php ... 'sqs' => [ 'driver' => 'sqs', // 'key' => env('AWS_ACCESS_KEY_ID'), // 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 'queue' => env('SQS_QUEUE', 'default'), 'suffix' => env('SQS_SUFFIX'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'after_commit' => false, ], ... 処理の実装 API routes/api.php ... // API 例 Route::get('/greeting', function () { return 'Hello World'; }); // 非同期Job呼び出し用 Route::get('/job', function (Request $request) { $message = $request->get("msg"); \App\Jobs\SimpleJob::dispatch($message); return 'OK'; }); Job SQS経由で非同期に実行するJob app/Jobs/SimpleJob.php <?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; class SimpleJob implements ShouldQueue { use Dispatchable; use InteractsWithQueue; use Queueable; use SerializesModels; /** @var string */ private $message; public function __construct(string $message) { $this->message = $message; } /** * Execute the job. * * @return void */ public function handle() { Log::info('Message: ' . $this->message); } } ローカル実行環境 localstack localstackの初期化用シェルを作成 docker/sqs/init.sh #!/bin/sh awslocal sqs create-queue --queue-name localstack_dead_letter_queue awslocal sqs create-queue --queue-name LaravelQueue \ --attributes '{"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-northeast-1:000000000000:localstack_dead_letter_queue\",\"maxReceiveCount\":3}"}' # Lambdaの作成 awslocal lambda create-function \ --function-name 'laravel-lambda-job-bridge' \ --runtime=provided.al2 \ --role=dummyrole \ --handler=worker.php awslocal lambda create-event-source-mapping \ --event-source-arn arn:aws:sqs:ap-northeast-1:000000000000:LaravelQueue \ --function-name "laravel-lambda-job-bridge" xdebug 設定ファイルを作成 docker/php/xdebug.ini [xdebug] xdebug.start_with_request=yes xdebug.client_host=host.docker.internal xdebug.client_port=9003 xdebug.log=/tmp/xdebug.log デバッグ用Dockerfile API用 debug.Dockerfile FROM bref/php-81-fpm-dev COPY --from=bref/extra-redis-php-81:0.11.19 /opt /opt COPY --from=bref/extra-xdebug-php-81:0.11.19 /opt /opt COPY docker/php/xdebug.ini /opt/bref/etc/php/conf.d/zz-xdebug.ini COPY --from=composer:2.1.12 /usr/bin/composer /usr/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer JOB用 jobs.debug.Dockerfile FROM bref/php-81 COPY --from=bref/extra-redis-php-81:0.11.19 /opt /opt COPY --from=bref/extra-xdebug-php-81:0.11.19 /opt /opt COPY docker/php/xdebug.ini /opt/bref/etc/php/conf.d/zz-xdebug.ini COPY --from=composer:2.1.12 /usr/bin/composer /usr/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer docker-compose docker-compose.yml version: "3.5" services: web: image: bref/fpm-dev-gateway ports: - '8000:80' volumes: - .:/var/task links: - php environment: HANDLER: public/index.php DOCUMENT_ROOT: public php: build: context: . dockerfile: debug.Dockerfile env_file: - .env.example environment: LOG_CHANNEL: stdout QUEUE_CONNECTION: sqs SQS_PREFIX: 'http://localstack:4566/000000000000' SQS_QUEUE: LaravelQueue AWS_DEFAULT_REGION: ap-northeast-1 XDEBUG_MODE: develop,debug PHP_IDE_CONFIG: serverName=docker volumes: - ~/.aws:/.aws - .:/var/task:ro # sqs localstack: image: localstack/localstack:latest environment: HOSTNAME_EXTERNAL: localstack DEFAULT_REGION: ap-northeast-1 DATA_DIR: /tmp/localstack/data SERVICES: sqs ports: - "4566:4566" volumes: - ./docker/sqs:/docker-entrypoint-initaws.d job: build: context: . dockerfile: jobs.debug.Dockerfile depends_on: - localstack env_file: - .env.example environment: LOG_CHANNEL: stdout QUEUE_CONNECTION: sqs SQS_PREFIX: 'http://localstack:4566/000000000000' SQS_QUEUE: LaravelQueue AWS_CONFIG_FILE: /.aws/config AWS_SHARED_CREDENTIALS_FILE: /.aws/credentials AWS_DEFAULT_REGION: ap-northeast-1 XDEBUG_MODE: develop,debug PHP_IDE_CONFIG: serverName=docker entrypoint: - php - artisan - queue:work volumes: - ~/.aws:/.aws - .:/var/task:ro ローカル実行 docker-compose up -d 動作確認 > curl 'http://localhost:8000/api/greeting' Hello World > curl 'http://localhost:8000/api/job?msg=Success' OK Dockerイメージの作成 Rest API用 Dockerfile bref/php-81-fpmを使用 Redisを利用する場合、brefphp/extra-php-extensionsから extra-redis-php-81を使用 今回は例示として追加 Dockerfile FROM bref/php-81-fpm COPY --from=bref/extra-redis-php-81:0.11.18 /opt /opt COPY . /var/task CMD [ "public/index.php" ] docker build -t {AWS::AccountId}.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-api-function:latest . Job 用 jobs.Dockerfile bref/php-81を使用 Redisを利用する場合、brefphp/extra-php-extensionsから extra-redis-php-81を使用 今回は例示として追加 jobs.Dockerfile FROM bref/php-81 COPY --from=bref/extra-redis-php-81:0.11.18 /opt /opt COPY . /var/task CMD [ "worker.php" ] docker build -f jobs.Dockerfile -t {AWS::AccountId}.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-jobs-function:latest . ECR dockerイメージを保存するリポジトリを作成 laravel-api-function aws ecr create-repository --repository-name laravel-api-function --region ap-northeast-1 laravel-jobs-function aws ecr create-repository --repository-name laravel-jobs-function --region ap-northeast-1 dockerイメージをリポジトリにプッシュ ECRログイン aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {AWS::AccountId}.dkr.ecr.ap-northeast-1.amazonaws.com リポジトリにプッシュ laravel-api-function docker push {AWS::AccountId}.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-api-function:latest laravel-jobs-function docker push {AWS::AccountId}.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-jobs-function:latest SQS 動作確認用のSQSキューを作成 aws sqs create-queue --queue-name LaravelQueue デプロイ CloudFormation API GatewayからLambda Functionを起動する CloudFormationファイルの作成 api.yaml AWSTemplateFormatVersion: "2010-09-09" Parameters: LogGroupName: Type: String Default: /aws/api-gateway/laravel FunctionName: Type: String Default: laravel-api-function QueueName: Type: String Default: LaravelQueue Resources: ApiFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Ref FunctionName MemorySize: 1024 Timeout: 300 Code: ImageUri: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/laravel-api-function:latest' ImageConfig: Command: - public/index.php PackageType: Image Environment: Variables: APP_ENV: development LOG_LEVEL: debug LOG_CHANNEL: stdout QUEUE_CONNECTION: sqs SQS_PREFIX: !Sub 'https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}' SQS_QUEUE: LaravelQueue Role: !GetAtt Role.Arn Role: Type: AWS::IAM::Role Properties: RoleName: RoleForLaravelApiFunction AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Sid: "" Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Path: / Policies: - PolicyName: LaravelApiFunctionPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogGroup Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*' - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*' - Effect: Allow Action: - sqs:SendMessage - sqs:GetQueueAttributes Resource: - !Sub 'arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${QueueName}' HttpAPI: Type: AWS::ApiGatewayV2::Api Properties: Name: !Sub '${AWS::StackName}-apigw' ProtocolType: HTTP DefaultStage: Type: AWS::ApiGatewayV2::Stage Properties: StageName: $default ApiId: !Ref HttpAPI AutoDeploy: true AccessLogSettings: DestinationArn: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${LogGroupName}' Format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod","routeKey":"$context.routeKey", "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength" }' DependsOn: - ApiGatewayLog ApiGatewayLog: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Ref LogGroupName RetentionInDays: 3 GetGreeting: Type: AWS::ApiGatewayV2::Route Properties: RouteKey: "GET /api/greeting" ApiId: !Ref HttpAPI Target: !Join - "/" - - "integrations" - !Ref GETIntegration GetJob: Type: AWS::ApiGatewayV2::Route Properties: RouteKey: "GET /api/job" ApiId: !Ref HttpAPI Target: !Join - "/" - - "integrations" - !Ref GETIntegration GETIntegration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref HttpAPI PayloadFormatVersion: "2.0" IntegrationType: AWS_PROXY IntegrationMethod: GET IntegrationUri: !GetAtt ApiFunction.Arn Permission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !Ref ApiFunction Principal: apigateway.amazonaws.com SourceArn: !Sub - 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpAPI}/*' - HttpAPI: !Ref HttpAPI CloudFormationデプロイ aws cloudformation deploy --template api.yaml --stack-name laravel-api-function --capabilities CAPABILITY_NAMED_IAM SQSをトリガーに起動する CloudFormationファイルを作成 jobs.yaml AWSTemplateFormatVersion: "2010-09-09" Parameters: FunctionName: Type: String Default: laravel-jobs-function QueueName: Type: String Default: LaravelQueue Resources: JobFunction: Type: "AWS::Lambda::Function" Properties: FunctionName: !Ref FunctionName MemorySize: 1024 Code: ImageUri: !Sub '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/laravel-jobs-function:latest' ImageConfig: Command: - worker.php PackageType: Image Environment: Variables: APP_ENV: development LOG_LEVEL: debug LOG_CHANNEL: stdout QUEUE_CONNECTION: sqs SQS_PREFIX: !Sub 'https://sqs.${AWS::Region}.amazonaws.com/${AWS::AccountId}' SQS_QUEUE: !Ref QueueName Role: !GetAtt Role.Arn Role: Type: AWS::IAM::Role Properties: RoleName: RoleForLaravelJobFunction AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Sid: "" Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Path: / Policies: - PolicyName: LaravelJobFunctionPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogGroup Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*' - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*' - Effect: Allow Action: - sqs:ReceiveMessage - sqs:DeleteMessage - sqs:GetQueueAttributes Resource: - !Sub 'arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${QueueName}' SQSEvent: Type: AWS::Lambda::EventSourceMapping Properties: BatchSize: 10 EventSourceArn: !Sub 'arn:aws:sqs:ap-northeast-1:${AWS::AccountId}:${QueueName}' FunctionName: !GetAtt JobFunction.Arn Enabled: true CloudFormationデプロイ aws cloudformation deploy --template jobs.yaml --stack-name laravel-jobs-function --capabilities CAPABILITY_NAMED_IAM 動作確認 ApiEndpointの取得 > aws apigatewayv2 get-apis { "Items": [ { "ApiEndpoint": "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com", "ApiId": "xxxxxxxxxx", "ApiKeySelectionExpression": "$request.header.x-api-key", "CreatedDate": "2021-12-02T00:00:00+00:00", "DisableExecuteApiEndpoint": false, "Name": "laravel-api-function-apigw", "ProtocolType": "HTTP", "RouteSelectionExpression": "$request.method $request.path", "Tags": {} } ] } apiの確認 /api/greeting > curl '{ApiEndpoint}/api/greeting' Hello World レスポンスとしてHello Worldが表示される jobの動作確認 /api/job > curl '{ApiEndpoint}/api/job?msg=Success' OK レスポンスとしてOKが表示される CloudWatch Logsの/aws/lambda/laravel-jobs-function に Message: Successのログが出力される まとめ PHP Laravelのコンテナイメージ化を行い、AWS Lambdaにデプロイ、動作確認するまでの手順を簡単に記載しました。 このまま業務に使用できるものではなく、実際にはVPCやRDSProxy等に接続するための設定、実装が必要になるでしょう。 また、Jobを非同期化するとしてもイベントメッセージがPHPに依存したJobクラスのシリアライズデータとなるため抽象化も難しく、APIとJobで実装をきれいに分けるのも困難です。 そのため、最適解ではありませんが、既存システムがPHP Laravelに依存しており、エンジニアに別の言語やフレームワーク等への移行を求める余裕がない場合、あるいはマイクロサービス化ほどの大げさなことにはしたくない場合、負荷を分散させる方法として手段の一つにはなると思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

まだレビューでそんなやりとりしてるの?PHPStanとPHP-CS-Fixerを導入して楽しよう(Github Actionsを添えて)

はじめに 弁護士ドットコム Advent Calendar 2021 記念すべき1日目?(2年連続) 本記事はあくまでも、Laravel MeetUp Okinawa でお話しした内容を記事にしたものになります。 本題 突然ですが、レビューでこんな事を言われた/言った経験はないだろうか。 「インデント!!これもう指摘するの3回目!!」 「ここの変数未定義だし、ここも型合ってないよ!!」 …………… ………………………… ……………………………………… 指摘された側 はその場では反省して、気をつける事だろう。 しかし、所詮は人間。同じミスはしてしまう。 指摘する側 も同じことを注意するのは面白いものではないし、 何よりロジックや設計のレビューに集中してレビューしたい。 静的解析と自動整形を導入してみない? そんな時に 静的解析 と 自動整形 の導入を検討してみよう。 静的解析(PHPStan) プログラムコードを実行せずにドキュメントやソースコードなどのチェックによって誤りや脆弱性を検出するテスト手法。 それらをPHPで提供されているのが静的解析ツール(今回はPHPStan)です。 今回はLaravel専用のPHPStanのラッパーライブラリLarastanを使用します。 静的解析とは 仕様 プログラムを実行せずに解析される(ただしPHPstanは一部実行する) 未定義の変数/メソッド/Class/プロパティなどを検出 その他PHPDocの構文不備や分岐のチェックも メリット 静的に解析される箇所は網羅的にテストができる テストを書く必要がないのでコストが少ない 変数の未定義など細かいエラーが事前に分かるのでコードレビューの手間が省ける デメリット 無限ループなどは検出できない PHPDoc PHPDocに引数や戻り値に型を宣言することで(実際の型宣言ではない)色々なメリットがあります。 型を強くしていきたいけど、型宣言はちょっとハードル高いなぁ...という時に導入すると良いでしょう! コードの見通しが良くなる IDEの補完が効くようになる 静的解析ができる arrayの中身を指定できる(array) 型宣言本格導入前に気軽に導入できる /** * プロフィール情報を取得する * * @param string|null $name * @param integer $age * @return string|null */ public function getProfile($name = null, $age) { if (!$name) { return null; } return "名前: {$name} 年齢: {$age}"; } Levelや範囲などの設定 静的解析のレベルはプロジェクトによって柔軟に設定することができます。 このレベル設定によって、0から初めて徐々にレベルを上げることでより厳密にプロジェクトを静的解析していくことが可能です。 includes 設定ファイルの読み込み paths 対象ファイル level 静的解析のレベル 0 ~ 8(max) excludePaths 無視ファイル phpstan.neon includes: - ./vendor/nunomaduro/larastan/extension.neon parameters: paths: - app/ - database/ - tests/ level: max excludePaths: - ./*/*/FileToBeExcluded.php checkMissingIterableValueType: false 使い方 ライブラリをプロジェクトに入れたら以下のようなコマンドで実行できます。 ./vendor/bin/phpstan analyze 自動整形(PHP-CS-Fixer) コーディング規約を設定した基準沿って自動でコーディングを統一する機能。 その機能をPHPで提供されているのが PHP-CS-Fixer (他にもPHP_CodeSnifferなどがある) です。 PHP-CS-Fixer では公式で PSR-1 や PSR-2 他にも Symfonyコミュニティ の標準 などが用意されていて、それらを使うことも自身でカスタマイズして使用することができる。 また VSCode でプラグインも用意されており、保存時に自動整形することも可能です。 カスタマイズ 自動整形のルールは独自でカスタマイズも可能です。 ver3.0.0 からはphpファイルになりました。 Finder::create() 対象ファイル setRiskyAllowed リスクが高い変更の許可 setRules カスタマイズするルール設定を記述 .php-cs-fixer.dist.php <?php declare(strict_types=1); $finder = PhpCsFixer\Finder::create() ->in([ __DIR__ . '/app', __DIR__ . '/config', __DIR__ . '/database/factories', __DIR__ . '/database/seeders', __DIR__ . '/routes', __DIR__ . '/tests', ]); $config = new PhpCsFixer\Config(); return $config ->setRiskyAllowed(true) ->setRules([ '@PhpCsFixer:risky' => true, 'array_syntax' => ['syntax' => 'short'], 'blank_line_after_opening_tag' => true, 'cast_spaces' => ['space' => 'single'], ]) ->setFinder($finder); 使い方 ライブラリをプロジェクトに入れたら以下のようなコマンドで実行できます。 整形箇所のピックアップ(実際に整形はされない) ./vendor/bin/php-cs-fixer fix -v --diff --dry-run 自動整形を適用する ./vendor/bin/php-cs-fixer fix -v --diff 静的解析 と 自動整形 を導入できました! おめでとうございます。 これによって実装者はレビューを出す前に細かなエラーに気付いて修正する事ができます! これでお互い細かなレビューを指摘する/される必要がなくなリました!やったね! ただもっと楽がしたい! 静的解析 は 自動整形 を導入できたけど、ローカルで実行し忘れたままレビューに投げちゃった(ToT) なんて事もあるでしょう。 そういう時は CI で自動に実行するようにしましょう。 CI(Github Actions) CIとは、Continuous Integrationの略で、継続的インテグレーションと呼ばれていて、 開発、テスト、リリースのサイクルが継続的に行われていく様子の事であり、それらを円滑に使用出来る様にしたものがCIツールです。 今回は Github Actions を使用しますが、CIのツールは Github Actions だけでなく、複数のツールが存在しています(Circle CIなど) Github Actions を使うメリットは無料(privateリポジトリは月2,000時間まで)という点と、普段利用している Github内のプロジェクトに .github/workflows/ ディレクトリを用意して設定ファイルを書くだけで利用できる手軽さにあります。(個人的見解) 他にも公式が用意しているテンプレートを簡単に使用することもできます。 設定方法 /.github/workflows/ にyaml形式で記入する on: CIが走るタイミングを決める jobs: stepsの集まり steps: jobを構成するAction などなど ここまで学んだ静的解析と自動整形をCIで設定してみる PHPStan マスターに対してプルリクエスト、マージが行われたタイミングでテストが走るように設定。 /.github/workflows/larastan.yml PHP-CS-Fixer こちらもLarastanと同様のトリガーでテストを実行します。 今回は dry-run で差分を出力までしかしていません。 自動整形を適用したい場合は一番下の run を ./vendor/bin/php-cs-fixer fix -v --diff に差し替えてください。 /.github/workflows/php-cs-fixer.yml CIであえて落ちる実装 あえてテストが落ちるように実装して、CIが走るようにプルリクを作ってみました。 <?php declare(strict_types=1); namespace App\Http\Controllers; use Illuminate\Http\Request; class ExampleController extends Controller { /** * @param int $id * @return int */ public function index(string $id): int { echo $test; $array = array(); return $id; } } プルリクを作成してCIが動いているのを見てみる 先ほどの実装でプルリクを作ってみた。 Github Actions を使っていると、Merge pull request の上にテストが走っているのが分かる。 テストが落ちると下の図のように、どのテストが落ちていて、Merge pull request が不活性になっているのが確認できる。 静的解析のテスト結果 確認すると以下の内容で、怒られているのが確認できる。 引数の型不一致 戻り値の型不一致 未定義の変数の使用 自動整形のテスト結果 確認すると以下の内容で、怒られているのが確認できる。 declareの改行 namespaceの改行 array()の使用 修正して再度プッシュ 先ほどの内容を修正して、再度プッシュしてみました。 そうするとテストが全部通って、Merge pull requestが活性化しているのが確認できました。 これでプルリクでレビュワーをアサインする前に自動的に細かいレビューで指摘されることがなくなりました!やったね! 最後に これまで学んだ内容は以下のリポジトリに公開していますので、ご自由にお使いください。 明日は @hkano さんの OpenSearch を使ってみる です!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

1年半振りのメジャーバージョンアップ(予定)!Laravel9の新機能ピックアップ!

Laravel Advent Calendar 2021 1日目の投稿です。 来月(2022年1月)、1年半ぶりのLaravelのメジャーバージョンアップするのでLaravel9の主要な変更点をまとめてみました。 リリース日 Laravel 8: 2020年9月 Laravel 9: 2022年1月(予定) Laravel 10: 2023年1月(予定) Laravel 11: 2024年1月(予定) Symfony6.0が2021年11月30日にリリースされました。それに伴ってLaravel 9のリリースが2022年1月に延期されています。 また、Laravel 9以降は半年周期のメジャーリリースが1年周期になっています。 Version PHP (*) Release Bug Fixes Until Security Fixes Until 6 (LTS) 7.2 - 8.0 September 3rd, 2019 January 25th, 2022 September 6th, 2022 7 7.2 - 8.0 March 3rd, 2020 October 6th, 2020 March 3rd, 2021 8 7.3 - 8.1 September 8th, 2020 July 26th, 2022 January 24th, 2023 9 (LTS) 8.0 - 8.1 January 25th, 2022 January 30th, 2024 January 28th, 2025 10 8.0 - 8.1 January 24th, 2023 July 30th, 2024 January 28th, 2025 インストール要件 最低でも PHP8.0 以上である必要があります。 Laravel 9の内部でSymfony6.0が利用されており、PHP8.0が最小要件があるためLaravel 9にも同じ制限が適用されます。 新機能ピックアップ Anonymous Stub Migrations Laravel v8.37.0 でクラス名の衝突を防ぐために匿名マイグレーション機能がリリースされました。 Laravel 9.xでは php artisan make:migration 実行時に生成されるファイルが匿名マイグレーションがデフォルトとなります。(Laravel8.xではデフォルトのマイグレーションテンプレートはクラス名付きで生成されますが、匿名マイグレーションは利用可能です。) use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('people', function (Blueprint $table) { $table->string('first_name')->nullable(); }); } }; これにより名前被りを気にせずマイグレーションファイルを作成できます。 マイグレーションファイル名は日付プレフィックスが付くので同名ファイルでも問題ありません。 また、稀によく発生していたマイグレーションクラスをリネームしてオートローダーが壊れる問題もこれで解消されそうです。 新しくクエリビルダーインターフェイスが追加 Illuminate\Database\Eloquent\Relations Illuminate\Database\Eloquent\Builder Illuminate\Database\Query\Builder これらのクエリビルダークラス群が1つのインターフェース Illuminate\Contracts\Database\QueryBuilder と契約しました。 文字列関数の内部実装の変更 最小要件がPHP8.0ということで、下記の関数の内部実装が変更されています。 Str::contains(); Str::startsWith(); Str::endsWith(); str_contains()、str_starts_with() および str_ends_with() 関数が利用されています。 現時点では特に非推奨となっていませんが、PHPの標準関数で実現できるので今後はもしかしたら非推奨になる関数かもしれませんね。 SwiftMailerからSymfonyMailerへ SwiftMailerが非推奨となり、Laravel9ではSymfonyMailerを使用するように変更されています。 lang ディレクトリがトップレベルへ Laravel8までは resources/lang でしたがLaravel9からトップレベルへ移動されました。 Flysystem v2 AWS S3をLaravelで操作したい時に使うライブラリthephpleague/flysystem-aws-s3-v3 v2系はLaravel8で動作しませんでしたが、Laravel9からv2系がサポートされます。 アップグレードの際はご注意ください。 https://github.com/laravel/framework/pull/33612 https://qiita.com/ucan-lab/items/61903ce10a186e78f15f Laravel インストーラにAPIオプションの追加 $ laravel new foo --api HTMLを返さないAPIシステムのためのapiオプションがLaravelインストーラに追加されるそうです。 css, js関連ファイルが削除されたLaravelプロジェクトテンプレートを構築します。 (管理画面はやっぱり簡単なHTMLを返したいとかありそう...笑 簡単に戻せるならアリかな?) Laravel8で追加された新機能 Laravel8.xで新しく追加された機能で気になったものをご紹介します。 Eloquent N+1検知機能 Laravel v8.43.0 でN+1検知機能がしれっと追加されていました。 N+1クエリーがあると例外が発生するため開発プロセスの初期段階でN+1クエリーを発見できます。 https://laravel-news.com/disable-eloquent-lazy-loading-during-development https://github.com/laravel/framework/pull/37363 https://github.com/laravel/framework/releases/tag/v8.43.0 Enum型のサポート Laravel v8.71.0 でEnum型を便利に扱えるようにキャスト機能やクエリー周りのサポートが行われています。 https://github.com/laravel/framework/pull/39608 https://github.com/laravel/framework/pull/39492 https://github.com/laravel/framework/pull/39597 https://github.com/laravel/framework/releases/tag/v8.71.0 https://github.com/laravel/framework/releases/tag/v8.70.0 参考 https://laravel-news.com/laravel-9 https://blog.laravel.com/laravel-9-release-date
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

1年半振りのメジャーバージョンアップ!Laravel9の新機能ピックアップ!

Laravel Advent Calendar 2021 1日目の投稿です。 来月、1年半ぶりのLaravelのメジャーバージョンアップするのでLaravel9の主要な変更点をまとめてみました。 リリース日 Laravel 8: 2020年9月 Laravel 9: 2022年1月(予定) Laravel 10: 2023年1月(予定) Laravel 11: 2024年1月(予定) Symfony6.0が2021年11月30日にリリースされました。それに伴ってLaravel 9のリリースが2022年1月に延期されています。 また、Laravel 9以降は半年周期のメジャーリリースが1年周期になっています。 インストール要件 最低でも PHP8.0 以上である必要があります。 Laravel 9の内部でSymfony6.0が利用されており、PHP8.0が最小要件があるためLaravel 9にも同じ制限が適用されます。 新機能ピックアップ Anonymous Stub Migrations Laravel v8.37.0 でクラス名の衝突を防ぐために匿名マイグレーション機能がリリースされました。 Laravel 9.xでは php artisan make:migration 実行時に生成されるファイルが匿名マイグレーションがデフォルトとなります。(Laravel8.xではデフォルトのマイグレーションテンプレートはクラス名付きで生成されますが、匿名マイグレーションは利用可能です。) use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('people', function (Blueprint $table) { $table->string('first_name')->nullable(); }); } }; これにより名前被りを気にせずマイグレーションファイルを作成できます。 マイグレーションファイル名は日付プレフィックスが付くので同名ファイルでも問題ありません。 また、稀によく発生していたマイグレーションクラスをリネームしてオートローダーが壊れる問題もこれで解消されそうです。 新しくクエリビルダーインターフェイスが追加 Illuminate\Database\Eloquent\Relations Illuminate\Database\Eloquent\Builder Illuminate\Database\Query\Builder これらのクエリビルダークラス群が1つのインターフェース Illuminate\Contracts\Database\QueryBuilder と契約しました。 文字列関数の内部実装の変更 最小要件がPHP8.0ということで、下記の関数の内部実装が変更されています。 Str::contains(); Str::startsWith(); Str::endsWith(); str_contains()、str_starts_with() および str_ends_with() 関数が利用されています。 現時点では特に非推奨となっていませんが、PHPの標準関数で実現できるので今後はもしかしたら非推奨になる関数かもしれませんね。 SwiftMailerからSymfonyMailerへ SwiftMailerが非推奨となり、Laravel9ではSymfonyMailerを使用するように変更されています。 lang ディレクトリがトップレベルへ Laravel8までは resources/lang でしたがLaravel9からトップレベルへ移動されました。 Flysystem v2 AWS S3をLaravelで操作したい時に使うライブラリthephpleague/flysystem-aws-s3-v3 v2系はLaravel8で動作しませんでしたが、Laravel9からv2系がサポートされます。 アップグレードの際はご注意ください。 https://github.com/laravel/framework/pull/33612 https://qiita.com/ucan-lab/items/61903ce10a186e78f15f Laravel8で追加された新機能 Laravel8.xで新しく追加された機能で気になったものをご紹介します。 Eloquent N+1検知機能 Laravel v8.43.0 でN+1検知機能がしれっと追加されていました。 N+1クエリーがあると例外が発生するため開発プロセスの初期段階でN+1クエリーを発見できます。 https://laravel-news.com/disable-eloquent-lazy-loading-during-development https://github.com/laravel/framework/pull/37363 https://github.com/laravel/framework/releases/tag/v8.43.0 Enum型のサポート Laravel v8.71.0 でEnum型を便利に扱えるようにキャスト機能やクエリー周りのサポートが行われています。 https://github.com/laravel/framework/pull/39608 https://github.com/laravel/framework/pull/39492 https://github.com/laravel/framework/pull/39597 https://github.com/laravel/framework/releases/tag/v8.71.0 https://github.com/laravel/framework/releases/tag/v8.70.0 参考 https://laravel-news.com/laravel-9 https://blog.laravel.com/laravel-9-release-date
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む