20210916のlaravelに関する記事は5件です。

【Laravel】検索機能の実装③ ~multipleを使って複数選択可能に~

以前⬇️の記事で、プルダウンから選択して検索できる機能を実装しました。 ここで作成した検索機能を、プルダウンから複数選択して検索できるようにアップデートしてみます。 作成物 「媒体」を複数選択して検索できるようになっています。 ビューの編集 今回編集したのは、「媒体」検索機能のselect要素のみです。 select要素のname属性を配列にして、選択されたoption要素を配列で受け取れるようにします。 またselect要素にmultiple属性を加えます。 index.blade.php <form action="{{ route('index') }}" method="GET"> //略 <label for="">媒体 //元のコード  <select name="medium"> <select name="medium[]" multiple> <option value="">全て</option> @foreach ($media_list as $media_item) <option value="{{ $media_item->getMedium() }}">{{ $media_item->getMedium() }}</option> @endforeach </select> </label> //略 </form> ルートの確認 ルートは以前作成した通りです。 web.php Route::get('/', [TeachingMaterialController::class, 'index'])->name('index'); コントローラーの編集 今回編集したのは「媒体」の検索部分のみです。 TeachingMaterialController.php class TeachingMaterialController extends Controller { public function index(Request $request) { //略 //元のコード if(!empty($media)) { $query->where('medium', '=', $medium); } //編集後のコード if(!$media[0]==null) { foreach($media as $medium) { $query->orwhere('medium', '=', $medium); } } //略 解説 元々のフォームでは、option要素の「全て」を選択した場合はvalue=""の通り空のデータとなり、$mediaの中身は空でした。 今回フォームのselect要素のname属性を配列にしたことで、「全て」を選択した場合の$mediaの中身は以下のようになります。よってif文の!empty($media)を!$media[0]==nullという条件に変更しました。 array ( 0 => NULL, ) if文の中で、$mediaで受け取った配列の中身ひとつずつに対して、データの絞り込みを行います。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】ルート情報の記述順によって発生するエラーと正規表現 制約を使った対策 (初学者向け)

はじめに 初めてQiitaに記事を投稿します。 ご指摘いただけますと幸いです。 1. 概要 ルートパラメータを使用する場合、記述の順番によっては DBに存在しないデータを処理しようとして、エラーが発生する可能性があります。 今回は、簡単なエラー発生例を記したあと、原因と対策について説明します。 ※本記事は初学者向けに詳しく解説しています。 2. 環境 PHP:7.4 Laravel:6.20 3. エラー発生の例 下記前提を踏まえた上で、エラーコードのサンプルを示します。 3.1 前提 ログインユーザーが記事を投稿できるsnsアプリを想定。 分かりやすいように最低限のメソッド、ルート情報のみを実装。 処理に対するルート情報のURI仕様は下記とする。 処理 HTTP Method URI Action Middleware 記事詳細画面を表示 GET articles/{記事のid} show web, guest 記事投稿画面を表示 GET articles/create create web, auth ルートパラメータは教材でよくある"id"を用いる。 viewは正しく実装されているものとして、今回は記載を省略する。 3.2 エラーが発生するコード 下記のコードにて、ログインした状態で記事投稿画面を表示させようとarticles/create にアクセスするとエラーが発生します。 routes/web.php Auth::routes(); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show'); Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); ※groupで括っているのは、他の処理を書いていた名残りです。 app/Http/Controllers/ArticlesController.php <?php namespace App\Http\Controllers; use App\Article; class ArticlesController extends Controller { public function create() { return view('articles.create'); } public function show($id) { $article = Article::find($id); return view('articles.show', compact('article')); } } 3.3 エラー内容 今回の例ではエラー内容は下記となります。 エラー内容 ErrorException Trying to get property 'title' of non-object (View: /var/www/html/resources/views/articles/show.blade.php) 上記は、「オブジェクトにはtitleというプロパティはない」というエラーになっています。 ( articles/show.blade.phpでは、$articleモデルオブジェクトからtitleプロパティを取得する記述をしています。 ) したがって、下記のいずれかが考えられます。 $articleモデルオブジェクトにtitleというプロパティが存在しない。 $articleモデルオブジェクト、titleというプロパティは存在しているが、アクセス修飾子がprivateまたはprotectedで設定されており、アクセスできない。 $articleモデルオブジェクトがそもそも存在しない。 エラー"Trying to get property of non-object"を解決したい また、createの処理を実行したつもりが、 なぜかshowアクションから表示するshow.blade.phpのファイルでエラーを指摘されています。 4. エラーの原因 4.1 原因 エラーの原因は、web.phpのshowアクションを実行するURIのルートパラメータにcreateを渡してしまっていることです。 これにより、showアクションにDBに存在しないパラメータが渡され、処理されます(nullが返ってくる)。 したがってblade側では$articleオブジェクトがそもそも存在していないため、エラーが発生します。 Laravelのルーティング優先度でつまづいた話 4.2 詳細解説 4.2.1 ルートパラメータについて まず、前提知識としてルートパラメータについて説明します。 今回showアクションのルートパラメータは{id}としています。 記事のidを受け取るので分かりやすく{id}にしていますが、下記の規則に従えば{x}でも{article}でもなんでも良いです。 Laravel 6.x ルーティング:ルートパラメーター ルートパラメータは、いつも{}括弧で囲み、アルファベット文字で構成してください。 ルートパラメータには、ハイフン(-)を使えません。 ちなみに今回の場合、パラメータを{article}とし、コントローラー側のアクションの引数を(Article $article)とすると、 ルートパラメータで指定したIDを持つ、モデルインスタンスが注入されて便利です。 Laravel 6.x ルーティング:モデル結合ルート ルートかコントローラアクションへモデルIDが指定される場合、IDに対応するそのモデルを取得するため、大抵の場合クエリします。 Laravelのモデル結合はルートへ直接、そのモデルインスタンスを自動的に注入する便利な手法を提供しています。 つまり、ユーザーのIDが渡される代わりに、指定されたIDに一致するUserモデルインスタンスが渡されます 4.2.2 ルートパラメータが受け付ける値 ルートパラメータですが、{id}にしたからといって数字のみ受け付けるのではなく、文字列も受け付けます。 リファレンスによるとデフォルトでは、/以外は受け付けるそうです。 Laravel 6.x ルーティング:スラッシュのエンコード Laravelのルーティングコンポーネントは、/を除くすべての文字を許可しています。 試しにパラメータに/を入れて実行しましたが、コントローラーへ行き着く前に404エラーレスポンスを返しました。 4.2.3 エラー発生の流れ 以上を踏まえて、エラー発生の原因について詳しく説明します。 web.phpに記載されたルート情報の処理は上から順番に実行されます。 showアクションのルート情報はcreateアクションのルート情報よりも先に記述されています。 つまり、 となって、viewメソッドにより、nullがbladeに渡されエラーが発生します。 リソースルートでCRUDを一括で設定すれば、その中では順番を考慮しなくても良いですが、 今回のようにshowは認証しない、createは認証するなど分ける場合は、ルートパラメータや記述順に注意する必要があります。 処理によって異なるエラー内容 1.今回の例では、showアクション内でfindメソッドを使用したことで、DBにデータがない場合の返り値がnullとなりましたが、コントローラーの処理を下記のようにしている場合は、nullを返さずに「HTTP 404エラー」が発生します。   ・findOrFailでモデルインスタンスを取得する処理を実装。   ・モデル結合ルートを使用している場合。 2.アクションでint型でidをタイプヒンティング(型宣言)した場合は、「int型を入力してください」 といったエラーが発生します。 Laravelのfind()とfindOrFail()の違い、使い分け方。初心者もよく分かる! Laravel 6.x ルーティング:モデル結合ルート 一致するモデルインスタンスがデータベースへ存在しない場合、404 HTTPレスポンスが自動的に生成されます。 PHPの型宣言(タイプヒンティング)の話 5. 対策 そもそもURI設計を適切にしていれば起きないのかも知れませんが、 起きてしまった場合の対策を3つ記載します。 5.1 ルートの記述順を変える。 今回の例で一番簡単な方法はルートの順番を変更することです。 下記のようにshowとcreateのルートを入れ替えることで、createが先に実行されるためエラーは発生しません。 web.php Auth::routes(); Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show'); 個人的に思うデメリットとしては、下記が挙げられます。 事前にURI設計をしてない場合、ルート情報が多くなるとややこしくなる。 ルートを追加した際に今後も同じエラーが発生する恐れがある。 5.2 web.phpに正規表現を使用 whereメソッドを使い、引数に正規表現を記載すると、パラメータを制限することができます。 ここでいう制限とはエラーを返さずに次の処理を実行することです。 ルート全体で当てはまるパラメータがなければ、404エラーを返します。 idの制約はリファレンスに記載されている'id', [0-9]+を用いています。 これは、idのパラメータは、「数字0~9で1文字以上」であることを意味します。 routes/web.php Auth::routes(); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show')->where('id', '[0-9]+'); //whereメソッドを追記 Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); Laravel 6.x ルーティング:正規表現制約 【5分でまるっと理解】PHP正規表現の使い方まとめ また、idは0が入ることはなく、1以上なので、そういった正規表現を行う場合は下記の表現ができるみたいです。 (上記の正規表現との挙動の違いは、0が入力された時、ルーティングの段階で404エラーを返すか、コントローラー以降の処理でエラーを返すかの違いになります。) 数字1~9で1文字以上の正規表現 ('id', '\+?[1-9][0-9]*'); 正の整数のことをききたいです 5.3 グローバル制約 正規表現は指定したルートパラメータ全てに適用することもできます。 下記のようにbootメソッド内でpatternメソッドを用います。 第1引数で指定したパラメータと同一のルートパラメータを、第2引数の制約で制限することができます。 app/Providers/RouteServiceProvider.php /** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::pattern('id', '[0-9]+'); //ルート制約を追加 parent::boot(); } Laravel 6.x ルーティング:グローバル制約 6. まとめ 今回は、実際に僕もハマったことのあるルートのエラーについての解説でした。 ルートの制約は実務ベースで使われるか不明ですが、 そういったところも含めてご指摘いただけますと幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】ルート情報の記述順によって発生するエラーと正規表現 制約を使った対策

はじめに 初めてQiitaに記事を投稿します。 ご指摘いただけますと幸いです。 1. 概要 ルートパラメータを使用する場合、記述の順番によっては DBに存在しないデータを処理しようとして、エラーが発生する可能性があります。 今回は、簡単なエラー発生例を記したあと、原因と対策について説明します。 ※本記事は初学者向けに詳しく解説しています。 2. 環境 PHP:7.4 Laravel:6.20 3. エラー発生の例 下記前提を踏まえた上で、エラーコードのサンプルを示します。 3.1 前提 ログインユーザーが記事を投稿できるsnsアプリを想定。 分かりやすいように最低限のメソッド、ルート情報のみを実装。 処理に対するルート情報のURI仕様は下記とする。 処理 HTTP Method URI Action Middleware 記事詳細画面を表示 GET articles/{記事のid} show web, guest 記事投稿画面を表示 GET articles/create create web, auth ルートパラメータは教材でよくある"id"を用いる。 viewは正しく実装されているものとして、今回は記載を省略する。 3.2 エラーが発生するコード 下記のコードにて、ログインした状態で記事投稿画面を表示させようとarticles/create にアクセスするとエラーが発生します。 routes/web.php Auth::routes(); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show'); Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); ※groupで括っているのは、他の処理を書いていた名残りです。 app/Http/Controllers/ArticlesController.php <?php namespace App\Http\Controllers; use App\Article; class ArticlesController extends Controller { public function create() { return view('articles.create'); } public function show($id) { $article = Article::find($id); return view('articles.show', compact('article')); } } 3.3 エラー内容 今回の例ではエラー内容は下記となります。 エラー内容 ErrorException Trying to get property 'title' of non-object (View: /var/www/html/resources/views/articles/show.blade.php) 上記は、「オブジェクトにはtitleというプロパティはない」というエラーになっています。 ( articles/show.blade.phpでは、$articleモデルオブジェクトからtitleプロパティを取得する記述をしています。 ) したがって、下記のいずれかが考えられます。 $articleモデルオブジェクトにtitleというプロパティが存在しない。 $articleモデルオブジェクト、titleというプロパティは存在しているが、アクセス修飾子がprivateまたはprotectedで設定されており、アクセスできない。 $articleモデルオブジェクトがそもそも存在しない。 エラー"Trying to get property of non-object"を解決したい また、createの処理を実行したつもりが、 なぜかshowアクションから表示するshow.blade.phpのファイルでエラーを指摘されています。 4. エラーの原因 4.1 原因 エラーの原因は、web.phpのshowアクションを実行するURIのルートパラメータにcreateを渡してしまっていることです。 これにより、showアクションにDBに存在しないパラメータが渡され、処理されます(nullが返ってくる)。 したがってblade側では$articleオブジェクトがそもそも存在していないため、エラーが発生します。 Laravelのルーティング優先度でつまづいた話 4.2 詳細解説 4.2.1 ルートパラメータについて まず、前提知識としてルートパラメータについて説明します。 今回showアクションのルートパラメータは{id}としています。 記事のidを受け取るので分かりやすく{id}にしていますが、下記の規則に従えば{x}でも{article}でもなんでも良いです。 Laravel 6.x ルーティング:ルートパラメーター ルートパラメータは、いつも{}括弧で囲み、アルファベット文字で構成してください。 ルートパラメータには、ハイフン(-)を使えません。 ちなみに今回の場合、パラメータを{article}とし、コントローラー側のアクションの引数を(Article $article)とすると、 ルートパラメータで指定したIDを持つ、モデルインスタンスが注入されて便利です。 Laravel 6.x ルーティング:モデル結合ルート ルートかコントローラアクションへモデルIDが指定される場合、IDに対応するそのモデルを取得するため、大抵の場合クエリします。 Laravelのモデル結合はルートへ直接、そのモデルインスタンスを自動的に注入する便利な手法を提供しています。 つまり、ユーザーのIDが渡される代わりに、指定されたIDに一致するUserモデルインスタンスが渡されます 4.2.2 ルートパラメータが受け付ける値 ルートパラメータですが、{id}にしたからといって数字のみ受け付けるのではなく、文字列も受け付けます。 リファレンスによるとデフォルトでは、/以外は受け付けるそうです。 Laravel 6.x ルーティング:スラッシュのエンコード Laravelのルーティングコンポーネントは、/を除くすべての文字を許可しています。 試しにパラメータに/を入れて実行しましたが、コントローラーへ行き着く前に404エラーレスポンスを返しました。 4.2.3 エラー発生の流れ 以上を踏まえて、エラー発生の原因について詳しく説明します。 web.phpに記載されたルート情報の処理は上から順番に実行されます。 showアクションのルート情報はcreateアクションのルート情報よりも先に記述されています。 つまり、 となって、viewメソッドにより、nullがbladeに渡されエラーが発生します。 リソースルートでCRUDを一括で設定すれば、その中では順番を考慮しなくても良いですが、 今回のようにshowは認証しない、createは認証するなど分ける場合は、ルートパラメータや記述順に注意する必要があります。 処理によって異なるエラー内容 1.今回の例では、showアクション内でfindメソッドを使用したことで、DBにデータがない場合の返り値がnullとなりましたが、コントローラーの処理を下記のようにしている場合は、nullを返さずに「HTTP 404エラー」が発生します。   ・findOrFailでモデルインスタンスを取得する処理を実装。   ・モデル結合ルートを使用している場合。 2.アクションでint型でidをタイプヒンティング(型宣言)した場合は、「int型を入力してください」 といったエラーが発生します。 Laravelのfind()とfindOrFail()の違い、使い分け方。初心者もよく分かる! Laravel 6.x ルーティング:モデル結合ルート 一致するモデルインスタンスがデータベースへ存在しない場合、404 HTTPレスポンスが自動的に生成されます。 PHPの型宣言(タイプヒンティング)の話 5. 対策 そもそもURI設計を適切にしていれば起きないのかも知れませんが、 起きてしまった場合の対策を3つ記載します。 5.1 ルートの記述順を変える。 今回の例で一番簡単な方法はルートの順番を変更することです。 下記のようにshowとcreateのルートを入れ替えることで、createが先に実行されるためエラーは発生しません。 web.php Auth::routes(); Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show'); 個人的に思うデメリットとしては、下記が挙げられます。 事前にURI設計をしてない場合、ルート情報が多くなるとややこしくなる。 ルートを追加した際に今後も同じエラーが発生する恐れがある。 5.2 web.phpに正規表現を使用 whereメソッドを使い、引数に正規表現を記載すると、パラメータを制限することができます。 ここでいう制限とはエラーを返さずに次の処理を実行することです。 ルート全体で当てはまるパラメータがなければ、404エラーを返します。 idの制約はリファレンスに記載されている'id', [0-9]+を用いています。 これは、idのパラメータは、「数字0~9で1文字以上」であることを意味します。 routes/web.php Auth::routes(); Route::get('articles/{id}', 'ArticlesController@show')->name('articles.show')->where('id', '[0-9]+'); //whereメソッドを追記 Route::group(['middleware' => 'auth'], function () { Route::get('articles/create', 'ArticlesController@create')->name('articles.create'); }); Laravel 6.x ルーティング:正規表現制約 【5分でまるっと理解】PHP正規表現の使い方まとめ また、idは0が入ることはなく、1以上なので、そういった正規表現を行う場合は下記の表現ができるみたいです。 (上記の正規表現との挙動の違いは、0が入力された時、ルーティングの段階で404エラーを返すか、コントローラー以降の処理でエラーを返すかの違いになります。) 数字1~9で1文字以上の正規表現 ('id', '\+?[1-9][0-9]*'); 正の整数のことをききたいです 5.3 グローバル制約 正規表現は指定したルートパラメータ全てに適用することもできます。 下記のようにbootメソッド内でpatternメソッドを用います。 第1引数で指定したパラメータと同一のルートパラメータを、第2引数の制約で制限することができます。 app/Providers/RouteServiceProvider.php /** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::pattern('id', '[0-9]+'); //ルート制約を追加 parent::boot(); } Laravel 6.x ルーティング:グローバル制約 6. まとめ 今回は、実際に僕もハマったことのあるルートのエラーについての解説でした。 ルートの制約は実務ベースで使われるか不明ですが、 そういったところも含めてご指摘いただけますと幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メールサーバー編】公開したアプリ(Laravel)を、ConoHa VPSを使ってメール送受信出来るまでの手順

○はじめに 以前、完成したアプリ(Laravel)を、ConoHa VPSを使って公開するまでの手順について記載しました。 その後、メールの送受信がまだだったので記載します。 ○大まかな手順 1. ConoHa VPSで、メールサーバーを立てる 2. アプリケーション側の.envの設定を変更する 以上です。 それでは、記載していきます。 ○メール送受信が出来るまでの手順 ①ConoHa VPSで、メールサーバーを立てる 記載すると言っても参考にした記事がかなり分かりやすく書かれています。 記事では、Railsでアプリを作成されていますが、最後のアプリケーション側の設定以外は同じです。 以下記事を参考に進めてください。 ②アプリケーション側の.envの設定を変更する MAIL_DRIVER=smtp MAIL_HOST=[メールサーバー ➡️ メールアドレスリスト → smtpサーバー記載] → 例)smtp.〜〜〜.conoha.io MAIL_PORT=587 MAIL_USERNAME=[先ほど設定したメールアドレス] MAIL_PASSWORD=[先ほど設定したパスワード] MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=[先ほど設定したメールアドレス] MAIL_FROM_NAME="〜〜〜運営" ← メールの送信元名になります(任意) 以下、忘れずに。 $ php artisan config:cache 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel-admin】form内での新規と編集の判別

マニュアルには載っていない 以下で判別可能 $form = new Form(new Task()); if ($form->isEditing()) { //編集時にしたい処理 }else{ //新規時にしたい処理 } return $form;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む