20210430のlaravelに関する記事は9件です。

laravel Docker 環境構築 「File Not Found」 エラー解決メモ

この記事の中盤辺りの「Laravel ウェルカム画面の表示」のところで File Not Found とエラーが出てしまいページが表示されなかったのですが、いろいろ調べてとりあえず動くようにはなったのでその解決メモを残しておきます。 結論としては、default.confのroot設定をroot /work/public;から root /work/laravel/public; に書き換えました。 default.conf server { listen 80; server_name example.com; root /work/public; <---この行を書き換える ... これで僕はとりあえず動くようにはなりましたが、これが正しい治し方かどうかはわかりませんのであくまでも応急処置という認識でよろしくお願いします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのゲートを使用してみた

Laravelには認証に加えて認可も手軽に実装できる方法を提供しています。Laravelの認可には「ゲート」と「ポリシー」の2つが用意されています。今回は「ゲート」を利用して特定のユーザーのアクションを制御しみます。 ゲートを利用するために、認証と必要なデータを用意するには下記の記事がおすすめです。 ゲートの作成 App\Providers\AuthServiceProviderクラスに処理を追加します。例では、各記事の更新ページは、ログインしているユーザーが作成したページのみ表示できるようにしています。 app/Providers/AuthServiceProvider.php namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; use App\Models\Article; use App\Models\User; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ // 'App\Models\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Gate::define('update-article', function (User $user, Article $article) { return $user->id === $article->user_id; }); } } 厳密な型の比較でusersテーブルのidとarticlesテーブルのuser_idを比較しています。ここで少しハマりポイントなのですが、articlesテーブルのuser_idをint型で定義していてもmodelではstringとして扱われてしまうので、この比較ではすべてfalseが返ってしまします。ですので、型をあわせるためにarticleモデルのほうでuser_idをintにキャストします。 app/Models/Article.php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Article extends Model { use HasFactory; protected $guard = ['id']; protected $casts = [ 'user_id' => 'integer' ]; } ゲートの利用 AuthServiceProviderで定義したゲートを利用してアクションを認可してみます。ArticlesControllerからゲート認可メソッドを呼び出して、認証済みユーザーが自身が作成したページ以外の記事更新ページをリクエストしたら403を返すようにします。 app/Http/Controllers/ArticlesController.php namespace App\Http\Controllers; use App\Models\Article; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; class ArticlesController extends Controller { // 更新メソッドなど public function edit(Article $article) { if (! Gate::allows('update-article', $article)) { abort(403); } return view('articles.edit', ['article' => $article]); } } 特定のユーザーにはすべてのページを見れるようにする 例えば、一般ユーザーは自身が作成したページのみしか更新できないようにして、管理者はすべてのページを更新可能にしたいことがあるかと思います。「ゲートチェックの割り込み」を利用することによってこの機能を実現できるようになります。ゲートチェックの割り込みはすべての認可メソッドの前後に挟むことができます。今回はすべての認可メソッドの前に割り込みし、「admin」ロールが付与されたユーザーはすべての更新ページを見れるようにします。 usersテーブルにroleカラムを追加 まずはmigrationを利用してusersテーブルにroleカラムを追加します。usersテーブルを作成するマイグレーションファイルはlaravelのインストール時に含まれているので、カラム追加用のマイグレーションファイルを用意します。 php artisan make:migration add_role_to_users_table --table=users マイグレーションファイル xxxx_xx_xx_xxxxxx_add_role_to_users_table.php <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class AddRoleToUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table->string('role', 16) ->after('password') ->default('user'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('role'); }); } } 作成したマイグレーションファイルを実行します。 php artisan migrate usersテーブルにroleカラムが追加されました。任意のユーザーのroleをadminに変更します。 UPDATE users SET role='admin' WHERE id=3 これで一般ユーザーと管理者ユーザーが作成できました。 割り込み処理を追加 Gateファサードのbeforeメソッドを使用することで、すべての認可チェックの前に特定の処理を実行できます。今回は認証済みユーザーのroleがadminの場合にアクションを許可するようにします。 app/Providers/AuthServiceProvider namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; use App\Models\Article; use App\Models\User; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ // 'App\Models\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Gate::before(function ($user, $ability) { if ($user->role === 'admin') { return true; } }); Gate::define('update-article', function (User $user, Article $article) { return $user->id === $article->user_id; }); } } これによって、adminロールが付与されたユーザーは自身が作成したページ以外のページも見れるようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Composerコマンドまとめ

はじめに PHPで開発をしていたら使うであろう Composer についてまとめました。 目次 前提知識 Composer composer.json composer.lock コマンド composer init composer install composer update composer require composer remove オプション 参考文献 前提知識 前提知識として以下のことを理解する必要があります。 Composer 依存関係にあるライブラリ( パッケージ )を管理してくれるツール のこと。 composer.json プロジェクトで使用されているパッケージを定義している。 composer.lock 依存するパッケージのリストが記載されていて、バージョンをロックしている。 コマンド "composer init" composer init 「composer.json」 を生成するために使用するコマンド。 プロジェクトの一番はじめに使用するものなので使用頻度はあまり高くありません。 "composer install" composer install 「composer.lock」 に書いてある内容を読み依存関係をインストールする。 composer init コマンド直後( 初回 )は 「composer.lock」 が生成されていないはずなので 「composer.json」 の内容が読まれ「composer.lock」 が生成される。 初回は install コマンドを使い二回目以降は update コマンドを使用する。 ※ 新しいパッケージを導入するときは別コマンド( composer.update か composer require )を使用します。 "composer update" composer update 「composer.json」 の内容をもとに update( 更新 ) する。 注意が必要で 「composer.lock」 の内容も update されるということ。複数人で開発していると、パッケージのバージョンに差異が出て開発した機能にバグが出てしまう恐れがある。 これを防ぐためにも update を使用するときは確認をリーダーに確認を取る、もしくは、パッケージを追加するときは require コマンドを使用すると良いかもしれない。(あくまで個人的見解なのでチームのルールがあれば従ってください) "composer require" composer require [パッケージ名] # 例えば # PHPMDを追加 composer require "phpmd/phpmd=@stable" パッケージを追加したいときに使用するコマンド。 "composer remove" composer remove [パッケージ名] # 例えば # PHPMDを削除 composer remove "phpmd/phpmd" パッケージの削除をしたいときに使用するコマンド。 オプション コマンドの最後に --dev をつけると 「composer.json」 の "require-dev" に読み込ませたり追加できたりすることができる。"require-dev" とは開発環境で使用している使用したいパッケージが定義されているということ。 他にもオプションはあるのでドキュメントを一度は覗いてみるとよいかもしれません。 参考文献 composer install Composerの使い方 composer install と composer updateの違い composer.json と composer.lock、install と update の違い
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】 laravel-breadcrumbsに引数・変数を複数渡す方法。エラー対処法|unexpected '=>' (T_DOUBLE_ARROW)、Too few arguments to function DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider::{closure}

Laravelのbreadcrumbsでパンくずの設定で変数を複数渡したい時に迷ったので対処方法をメモとして記録。 状況 パラメータ付きのURLを指定する時に、Breadcrumbs::renderの第二引数でデータを渡すが、この時に2つのデータを渡したい。 Breadcrumbs::render('ルート名', 渡すデータ) そして、bredcrumbs.phpのfunctionで複数のデータを受け取り使いたい。 対処法 ビューのBreadcrumbs::renderの第二引数は配列のKey-value形式でデータを渡す。 breadcrumbs.phpでは一つの変数として受け取り、キー名を指定する。 view(.balde.php) {{ Breadcrumbs::render('media.show', ['name' => $name, 'media_slug' => $media_slug] ) }} データとして、nameというキー名で$nameを、media_slugというキー名で$media_slugを渡す。 breadcrumbs.phpでは第二引数としてこのひとまとまりの配列データが渡される。 渡されたデータはfunctionの中で任意の変数に代入する。ここでは$arrayに入れる。 呼び出しは、$array['name']、$array['media_slug']となる。 breadcrumbs.php Breadcrumbs::for('service.media.show', function ($trail, $array) { $trail->parent('top'); $trail->push( $array['name'], route('media.show', [ 'media_slug' => $array['media_slug']])); }); データを渡した部分のみを抜粋すると以下のようになる。 $trail->push( '表示するパンくず名', route('ルート名', [ 'ルートに渡すデータのキー名' => '値']])); 表示するパンくず名に$array['name']を指定し、パラメータ付きのルート(media.show)に渡すデータを$array['media_slug']としている。 以上でパンくずおよび無事ページが表示された。 エラー functonで変数を複数指定した場合 Breadcrumbs::render('ルート名', 渡すデータ)で指定できるデータは1つのみ。複数ある場合は配列で渡す。 このため、breadcrumbs.phpのfunctionで変数を複数指定するとエラーになる。 エラー例 Breadcrumbs::for('service.media.show', function ($trail, $name, $media_slug) { $trail->parent('top'); $trail->push( $array['name'], route('media.show', [ 'media_slug' => $array['media_slug']])); }); ErrorException (E_ERROR) Too few arguments to function DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider::{closure}(), 2 passed in /app/vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsGenerator.php on line 68 and exactly 3 expected (View: /app/resources/views/layouts/base.blade.php) (View: /app/resources/views/layouts/base.blade.php) viewで変数を複数指定した場合 Breadcrumbs::render('ルート名', 渡すデータ)で指定できるデータは1つのみのため、ここでデータを複数指定するとエラーになる。 エラー例 {{ Breadcrumbs::render('service.media.show', 'name' => $name, 'media_slug' => $media_slug ) }} ErrorException (E_ERROR) syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ')' (View: /app/resources/views/layouts/base.blade.php) (View: /app/resources/views/layouts/base.blade.php) 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】 laravel-breadcrumbsでトップページはパンくずなし、パラメータ付きページの条件分岐方法

Laravelのパンくずを簡単に設定できるlaravel-breadcrumbsで、ルートによって条件分岐を設定してパンくずを出し分ける方法について。 例えば、通常はルート名に一致するパンくずを表示させるが、それ以外に、トップページにはパンくずを設置しない方法や、パラメータ付きページのパンくずの設定方法について。 通常のパンくずの場合 パラメータを必要とせず、ルート名に対応するパンくずを表示するには、引数なしでBreadcrumbs::render()を呼び出せばOK。 ビュー(.balde.php) {{ Breadcrumbs::render() }} この場合、現在表示されているページと一致するルート名のパンくずが適用される。Breadcrumbs::for('ルート名', function ($trail){処理}); 実例 例えばルート名がblog.indexというページを開いた場合、{{ Breadcrumbs::render() }}にはホーム > ブログ一覧が入る。 routes/breadcrumbs.php Breadcrumbs::for('top', function ($trail) { $trail->push('ホーム', route('top')); }); // ホーム > ブログ一覧 Breadcrumbs::for('blog.index', function ($trail) { $trail->parent('top'); $trail->push( 'ブログ一覧', route('blog.index')); }); トップページにパンくずを表示させない トップページにパンくずを表示させない場合は、Breadcrumbs::renderを指定しなければいい。 ▼トップのルーティング web.php(ルーティング) Route::get('/', ['as' => 'top', 'uses' => 'TopController@index']); ▼ビューでパンくずを設定 ビュー(.balde.php) @if(Route::currentRouteName() === 'top') @else {{ Breadcrumbs::render() }} @endif ルート名がtopの場合にはBreadcrumbs::renderの処理をスキップする。トップページ以外はbreadcrumbs.phpの中で一致するパンくずを表示する。 パラメータ付きページへのパンくず設定方法 パラメータ付きページにパンくずを設定する場合は、パンくずのリンクで指定したルート名にパラメータに入れる値を指定する必要がある。 これを指定しないと、Missing required parametersというエラーが発生する。 ▼パラメータ付きページのルーティング例 web.php(ルーティング) Route::get('media/{media_slug}', 'ServiceController@show')->name('media.show'); ルート名media.showは{media_slug}というパラメータが必須となっている。 (1)コントローラでパラメータをビューに渡す コントローラの中でビューにパラメータを渡す必要がある。 コントローラ public function show(Request $request, string $media_slug) { return view('media.show', [ 'media_slug' => $media_slug ] ); } (2)ビューでパンくずを呼び出す ビュー(.balde.php) @if(Route::currentRouteName() === 'media.show') {{ Breadcrumbs::render('media.show', $media_slug) }} @else {{ Breadcrumbs::render() }} @endif コントローラから受け取った変数をrenderの第二引数に指定する。 (3)パンくずの設定 routes/breadcrumbs.php Breadcrumbs::for('top', function ($trail) { $trail->push('ホーム', route('top')); }); Breadcrumbs::for('service.media.show', function ($trail, $media_slug) { $trail->parent('top'); $trail->push( $media_slug, route('media.show', [ 'media_slug' => $media_slug])); これで、ビューに HOME > {media_slug} を表示することができる。 まとめ 上記をまとめて記述するとビューとパンくずの設定は以下のようになる。 ビューのパンくず設定抜粋 @include('layouts.header') @if(isset($exception)) {{ Breadcrumbs::render('errors.common', $exception) }} @elseif(Route::currentRouteName() === 'top') @elseif(Route::currentRouteName() === 'media.show') {{ Breadcrumbs::render('media.show', $media_slug) }} @else {{ Breadcrumbs::render() }} @endif ビューのbodyタグ全体の例 ビュー(.balde.php) <body id="js-opinion" class="@yield('bodyClass')"> @include('layouts.header') @if(isset($exception)) {{ Breadcrumbs::render('errors.common', $exception) }} @elseif(Route::currentRouteName() === 'top') @elseif(Route::currentRouteName() === 'media.show') {{ Breadcrumbs::render('media.show', $media_slug) }} @else {{ Breadcrumbs::render() }} @endif <div class="@yield('contentClass')"> @yield('content') </div> @include('layouts.footer') <script src="{{ mix('js/lazyload.js') }}"></script> @yield('jsCodeBody') </body> パンくずの設定 routes/breadcrumbs.php Breadcrumbs::for('top', function ($trail) { $trail->push('ホーム', route('top')); }); // ホーム > ブログ一覧 Breadcrumbs::for('blog.index', function ($trail) { $trail->parent('top'); $trail->push( 'ブログ一覧', route('blog.index')); }); // ホーム > {media_slug} Breadcrumbs::for('service.media.show', function ($trail, $media_slug) { $trail->parent('top'); $trail->push( $media_slug, route('media.show', [ 'media_slug' => $media_slug])); 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】パンくずの設定ミスによるエラー対処法|Missing required parameters for laravel-breadcrumbs

Laravelでパンくずを設置するのに便利なlaravel-breadcrumbsで以下のようなエラーが出た場合の対処法。 ・エラーの例 Missing required parameters for [Route: media.show] [URI: media/{media_slug}]. (View: /app/resources/views/layouts/base.blade.php) 原因 パラメータ付きのルートをパンくずで指定する時に、パラメータの値を渡さないために発生。 対処法 パンくずの設定でルート名を指定する時に必要なデータを渡す。 ポイントは2つ。 1. functionの引数で変数を指定する。 1. routeの指定でデータを渡す。 例えば、URIがmedia/{media_slug}のようにパラメータを必要とする場合に、パンくずの中でルート名を指定した場合は以下になる。 web.php Route::get('media/{media_slug}', 'ServiceController@show')->name('media.show'); routes/breadcrumbs.php Breadcrumbs::for('media.show', function ($trail, $media_slug) { $trail->parent('media.index'); $trail->push( $media_slug, route('media.show', [ 'media_slug' => $media_slug])); ・function ($trail, $media_slug) $trailはパンくずを表示するために必須の変数。第二引数でルートに渡すデータを指定する。 なお、上記例では、パンくずで表示する名前にもこの変数を指定している。 ・route('ルート名', [ 'キー名' => 値 ]) ルート名がパラメータを持つ場合は、Key-Valueの形式で第2引数でデータを渡す必要がある。 なお、キー名をパラメータ名と合わせる必要はない。(何でもいい)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでAjaxを実装する場合のリンク集

はじめに LaravelでAjaxを実装する際に、良いチュートリアルが存在せず、 Laravel内での解決方法もあまりなかったので、実装方法を別途探りました。 結論から言うと、Laravel内ではView/BladeでAjax用の機能を提供していないので、 jQuery等のJavaScriptのライブラリを組み込んでAjax部分は別途実装する必要あります。 その時に調べた情報のリンク集としてまとめました。 コードとかは気が向いたら、別途記事にする予定です。 参考 Laravel7 ajaxでviewを返す方法 【Laravel5】FormRequestのバリデーション結果をJSON APIで返す 完全な手順!LaravelでAjaxコンテンツをつくる方法 【Laravel】LaravelでAjax(jQuery)を使用する Laravel、Ajaxを用いて動的なコメント閲覧画面の作成 LaravelでAjaxを使う方法。サーバにPOSTしてResponseを返す
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】コントローラで渡した配列のデータをビューで表示する方法と注意点

Laravelのデータ受け渡しで、コントローラで配列型の変数を渡した時に、ビューでそのデータを受け取ったり表示する時に迷うことが多いので改めてまとめてみた。 結論 ・コントローラ側では$配列名 ・ビュー側では$配列の中のキー名 となる。 コントローラ public function media(Request $request) { $array = [ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', ]; return view('xxx', $array); } ビュー(xxx.blade.php) {{$key1}} ▼ブラウザの表示 エラー|配列名は指定できない ビュー側で配列名は指定できない。配列名の変数を指定するとエラーになる。 ビュー(xxx.blade.php) {{$array}} エラー ErrorException (E_ERROR) Undefined variable: 指定した配列名 (View: /app/resources/views/xxx.blade.php) つまり、コントローラからビューに配列データを渡した時、渡されるのは配列の中身のみとなる。 ビューに渡されるデータ コントローラで渡すデータに配列を指定するのは以下と同じになる。 コントローラ public function media(Request $request) { $array = [ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', ]; return view('xxx', $array); } ↓↑同じ コントローラ public function show(Request $request) { return view('xxx', ['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

modalで確認してから、画像を削除する

web.php Route::delete('/shop', 'ShopController@delete')->name('delete'); ShopController.php use Illuminate\Http\Request; use App\Item; use Illuminate\Support\Facades\Storage; class ShopController extends Controller { public function delete(Request $request) { $deleteItem = Item::find($request->id); $deletepath = $deleteItem->file_path; // データベースのfile_path名は確認していたほうが確実(× 'public/uploads'. ) Storage::delete('public/' . $deletepath); $deleteItem->delete(); return redirect('/リダイレクト先'); } } shop.blade.php <!-- Bootstrap導入 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <!-- Bootstrap Javascript(jQuery含む) --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> @foreach($images as $image) <!-- </form>はmodalのsubmitの下に記載してある --> <form action="/shop" method="post"> @method('delete') @csrf <!-- nameプロバティとvalueプロパティがポイント --> <button type="button" class="buy-confirm btn btn-success" name="id" value="{{ $image->id }}" data-toggle="modal" data-target="#confirm-buy" style="width: 18rem; float: left; margin: 16px;"> <img src="{{ Storage::url($image->file_path) }}" style="width: 100%;"/> <p>{{ $image->file_name }}</p> </button> @endforeach <!-- Modal --> @foreach($images as $image) <div class="modal fade" id="confirm-buy" tabindex="-1" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">確認</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> 購入しますか? </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">いいえ</button> <!-- 商品imageと同じidを持たせることで、同じvalueを持たせることになる --> <button type="submit" class="btn btn-success" id="buybtn" name="id">はい</button> </form> </div> </div> </div> </div> @endforeach <script> $('.buy-confirm').click(function(){ $('#buybtn').val( $(this).val() ); }); </script>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む