- 投稿日:2021-01-22T23:29:47+09:00
Laravelで画像を表示する方法
PHP、Laravelの初学者です。
Laravelで画像を表示させる方法がわかったので、メモしておきたいと思います。
※ 使用しているLaravelのバージョンは6.xです。違うバージョンをご使用の方はご注意ください。
また、私はMacを使用しているので、Windowsをご使用の方もご注意ください。Laravelで画像を表示させる方法
①「自分のプロジェクト/storage/app/public」の中に利用したい画像を置く。
私は「/storage/app/public」にtop-page.jpgを入れました(以下の画像をご覧ください)。
② シンボリックリンクを張る
Laravel6.xの公式ドキュメントを見たところ、
「/storage/app/public」においた画像を使えるようにする(Webからのアクセスを許す)には、
「『public/storage』から『storage/app/public』へシンボリックリンクを張る」という作業が必要になるようです。シンボリックリンクって何だろう??
シンボリックリンクとは、オペレーティングシステム(OS)のファイルシステムの機能の一つで、特定のファイルやディレクトリを指し示す別のファイルを作成し、それを通じて本体を参照できるようにする仕組み。
んー。まだ難しい。
もう少し噛み砕いて説明された記事がありました。要は「代理人」のような役割を持つのが、このシンボリックリンクだそうです。
例を引用させていただくと例えば、ファイルAと、シンボリックリンクA’があるとしましょう。
シンボリックリンクA’は、ファイルAのシンボリックリンクです。このシンボリックリンクA’を開くと、ファイルAが開きます。
ファイルAを直接開いたのと同じ結果です。要は、代理人みたいなものですね。
シンボリックリンクは、自分がそのファイルやフォルダであるかのように振る舞います。とのことです。
さて、前置きが長くなりましたが、このシンボリックリンクを張るには、以下のコマンドを実行しましょう。
ターミナルphp artisan storage:link③シンボリックリンクを張ることができたら、ビューファイルに以下のように記述すれば画像を表示できます。
index.blade.php<img src="/storage/top-page.jpg">こんな感じで成功しました!
以上です。
何かありましたらコメントで教えていただけますと幸いです。ここまで読んでいただきありがとうございました。
- 投稿日:2021-01-22T22:47:41+09:00
【Laravel】オレ得 Eloquent/QueryBuilderメモ集
概要
よく忘れるので自分用メモ✏️
※日々追加...データ取得
get
$users->get(); // 返り値は collection<StdClass>first
$users->first(); // 返り値は StdClassWHERE句
whereIn(含む)
$users->whereIn('id', [1, 2, 3]);whereDate(日付)
$query->whereDate('created_at', '=', '2020-01-22');JOIN句
LeftJoin
DB::table('users as U') ->select('U.name, U.age, J.role') ->leftJoin('jobs as J', 'j.user_id', '=', 'U.id');AND/OR
AND検索
$query ->where('name', '=', $value1) ->where('age', '=', $value2);OR検索
$query ->where('name', '=', $value1) ->orWhere('age', '=', $value2);OR+AND検索
$query->where(function ($query) use ($keyword) { $query->where('name', 'LIKE', '%' . $keyword . '%') ->orWhere('age', 'LIKE', '%' . $keyword . '%'); });
- 投稿日:2021-01-22T22:15:55+09:00
JSとLaravelでAPI通信する際に日付データを合わせる(unixtime <-> Date)
概要
サーバーさん => Sさん
フロントさん => Fさんあるときこんなやりとりを目撃しました。
Sさん < 日付のフォーマットは20200222で送ってください
Fさん < ここは2020/02/22で送ってください
Sさん < この場合は2020-02-22で送ってください
続く....そのとき第三者の私はこう思いました。
私 < Unixtimeでやりとりすれば、同じフォーマットでやりとりできるんじゃね?と...
やってみた。
javascript// Date -> UnixTime new Date().getTime() / 1000; // 1611320223.828 // UnixTime -> Date new Date(unixTime * 1000); // Fri Jan 22 2021 21:57:44 GMT+0900 (日本標準時)※バックエンドはLaravelを使用しています
php// Date -> UnixTime $date = new DateTime('now'); $date->format('U'); // "1611320663" // UnixTime -> Date $dateTime = new DateTime('@' . (int)$unixTime); $dateTime->setTimeZone(new DateTimeZone('Asia/Tokyo')); // 2021-01-22 22:04:23.0 Asia/Tokyo (+09:00)感想
一旦これでUnixtimeでやりとりできそう!
もっと良いやり方などがありましたら教えてください。
- 投稿日:2021-01-22T18:55:48+09:00
Laravel6でmorphToのリレーション先テーブルの参照するカラムを変更したい時
そもそもそんなテーブル設計は間違っているということはいったんさておき、表題の対応しなければいけないことがあったのでメモとして残す
default_templates - template_id - name user_created_templates - id - name reports - id - templatable_id - templatable_type運用者が頻繁に更新する自動採番IDを持たないテーブルと、ユーザーが自分でCURDするテーブルがあってそれらをポリモーフィックで呼び出したいというケース。
いずれのテーブルもプライマリキーがidという場合にはモデル内部で
morphTo
で参照すればいい。今回のケースで言えば
templatable_type
に応じて参照するキーを動的に変更したいので下記のようにすると参照可能。Models/report.phpclass report exteds Model { public function templatable() { $ownerKey = $this->getAttribute('templatable_type') === 'App\Models\DefaultTemplate' ? 'template_id' : 'id'; return $this->morphTo('templatable', null, null, $ownerKey); } }
- 投稿日:2021-01-22T15:55:57+09:00
Laravel checkboxで複数取得する方法
はじめに
inputのcheckboxを使って
1. 複数チェックの取得
2. チェックしたデータを保持する方法
をまとめてみました。
テーブル設計とリレーション
今回は
usersテーブル
とcategoriesテーブル
使っていきます。userは複数のcategoryを持ち、categoryも複数のuserに紐づけられているので
多対多のリレーションになります。
テーブル設計
◎usersテーブル
migrationpublic function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); }); }
◎categoriesテーブル
migrationpublic function up() { Schema::create('categories', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); }
◎category_userテーブル
migrationpublic function up() { Schema::create('category_user', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('category_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users')->OnDelete('cascade'); $table->foreign('category_id')->references('id')->on('categories')->OnDelete('cascade'); $table->timestamps(); }); }
category_userテーブルでmigration$table->foreign('user_id')->references('id')->on('users')->OnDelete('cascade'); $table->foreign('category_id')->references('id')->on('categories')->OnDelete('cascade');でOnDelete('cascade')をつけておきましょう。 後々でdetachのときに一緒に削除するためです
リレーション設計
User.phppublic function categories() { return $this->belongsToMany(Category::class); }ここまで出来たら次はコントローラーの作成に入ります
コントローラー設計
Contorllerpublic function update(Request $request) { $user = Auth::user(); $user->categories()->detach(); $user->categories()->attach($request->category);
$user->categories()
でリレーションをして、attach($request->category)
でリクエストするカテゴリーを紐付けます。テーブルで
OnDelete('cascade')
をつけたのは、detachで削除するときに、user_id
,category_id
を削除するためです。次はBladeの設計です
Bladeの設計
ここが結構悩みました。 データの取得は出来たのですが、編集するときにデータの保持するのがなかなか詰まりました。
最初はoldを使ってデータ保持をやろうとしたのですがなかなかうまく行かず、oldを使わないでchecked
が含まれてるときでif文を作りました。
blade@foreach ($categories as $category) @if($user->categories->contains('id', $category->id)) <input type="checkbox" name="category[]" value="{{ $category->id}}" checked> @else <input type="checkbox" name="category[]" value="{{ $category->id}}"> @endif <label for=""> {{ $category->name }} </label> @endforeach指定したidを判定するためにコレクションの
contains()
メソッドを使って、指定したidが含まれているか確認しました。ただ、oldを使ってデータ保持もやりたかったので、三項演算子を使って下記のようにも書いてみました。
blade@foreach($categories as $category) <input type="checkbox" name="category[]" id="" value="{{ $category->id }}" {{ $category->id == old('category', $user->categories->contains('id', $category->id) ?? '') ? 'checked' : ''}} > <label for="category"> {{ $category->name }} </label> @endforeach保存して、また編集画面に遷移してもチェックボックスにcheckがついています!
色々なやり方がありますがご参考までに!!参考
- 投稿日:2021-01-22T15:37:27+09:00
【PHP初心者】Laravelを2週間触ってみて理解したこと②【ルーティング】
1.はじめに
こんにちは。nakaです。
昨晩ホームベーカリーをセットし、今朝は小麦のいい匂いで朝を迎えました( ˘ω˘ )
パンが大好きなのでとても癒されました・・・さて本題に入ります!前回に引き続きLaravelについてまとめたいと思います。
前回の記事:【PHP初心者】Laravelを2週間触ってみて理解したこと今回はルーティングについてです。
2.ルーティングとは
初めてLaravelのソースを見たとき、「えーとControllerやろー・・・・ん?」
controllerにリクエストのURLがなくてびっくりしました。
Laravelは代わりにルーティングと呼ばれるものがその役割を担っているようです。
ルーティングのルートが「経路」と訳されるように、ユーザからのリクエストを受け取り、ある処理を実行するまでの案内人のようなイメージですね。ルーティングは「routes/web.php」で設定できます。
Larabelをインストール後は、デフォルトのページの設定がされています。web.php<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); });3.ルート定義メソッド
それでは上記ファイル(web.php)に書くHTTPリクエストに定義できるメソッドを見てみましょう。
メソッドでよく見るものは「GET」「POST」ですかね。// GETリクエスト Route::get($uri, $callback); // POSTリクエスト Route::post($uri, $callback); // putリクエスト Route::put($uri, $callback); // patchリクエスト Route::patch($uri, $callback); // deleteリクエスト Route::delete($uri, $callback);ちなみにルーティングにはルートファザードを使います。
ファザードとはクラスをインスタン化せずに実行できる機能のことです。4.コントローラーのルーティング
基本の形
例えばコントローラーへルーティングする際は、以下のように書きます。
web.phpRoute::get('sample', 'SampleController@index');
http://xxx/sample
へアクセスすると、SampleControllerのindex()が呼ばれます。パラメータ付き
またURLからパラメーターを取得したい場合は、以下のように書きます。
web.phpRoute::get('sample/edit/{id}', 'SampleController@edit');SampleContoroller.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class SampleController extends Controller { public function edit($id) { print_r($id); } }
http://xxx/sample/edit/1
へアクセスすると、「1」というパラメータを取得し、SampleContoroller.phpのedit()の$idという変数で値を取得できます。ルーティングに名前を付ける
またルーティングに名前をつけることもできます。
URLをわざわざ書かなくも名前で呼び出せます。web.phpRoute::get('sample', 'SampleController@index')->name('sample.index');6.リダイレクトのルーティング
上記の名前をつけると便利
web.phpRoute::get('sample', 'SampleController@index')->name('sample.index');SampleContoroller.phpreturn redirect()->route('sample.index');5.ルートのグループ化
ルーティングをグループ化できます。
URLをまとめるときに使う「prefix」
管理者と会員など権限が複数の時に使うと便利
// ごちゃごちゃ Route::get('admin/top', 'AdminContoroller@top'); Route::get('admin/setting', 'AdminContoroller@setting');// 見やすい Route::prefix('admin')->group(function () { Route::get('top','AdminContoroller@top'); Route::get('setting','AdminContoroller@setting'); });名前空間をまとめる「namespace」
配置先をまとめることができます。
以下の場合は、"App\Http\Controllers\Admin"のディレクトリ内を示しています。App\Http\Controllers\Admin\TopColler@top App\Http\Controllers\Admin\SettingContoroller@setting// ごちゃごちゃ Route::get('top','Admin\TopColler@top'); Route::get('setting','Admin\SettingContoroller@setting');// 見やすい Route::namespace('Admin')->group(function () { Route::get('top','TopColler@top'); Route::get('setting','SettingContoroller@setting'); });他ミドルウェアをまとめる「middleware」、ドメインをまとめる「domain」、ルート名をまとめることもできます。複数を一気に設定もできます(今回は割愛)
6.さいごに
忘れていましたがルーティングは
php artisan route:list
で一覧が確認できます。ルーティングを理解するとソースの流れがわかりますね。
次回はBladeについて書く予定です(゜レ゜)
マークダウン少しづつ慣れてきた。参考記事
Laravelルーティングの基本とよく使われるルーティングパターン
routesを使いこなす(3)prefixでgroupを分割
- 投稿日:2021-01-22T14:40:19+09:00
【Laravel】繰り返し処理は@includeを使う。PHPはビューではなくコントローラに記述する(リファクタリング)
リファクタリングの個人メモです。
ビューの中に繰り返し処理を記述している場合は、処理を別ファイルに切り出し、
@include
で呼び出すPHPの処理はビューの中に書かず、コントローラで渡す(他でも使う処理の場合は自作のヘルパー関数を作って渡す)
リファクタリング事例
リファクタリング前のコード
以下のように同じコードが繰り返されている処理をリファクタリングする。
phones.balde.php<div class="p-service__list"> <section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> <section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'android' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> <section> <h2 class="c-page-headline">xperia</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'xperia' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> </div> </div>コードを見ると
section
が繰り返されているのがわかる。繰り返しのコード<section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section>
@foreach(__('service') as $service)
言語ファイル( resources > lang > ja )のservice.phpに記述された配列を、$service
として一つづつ抜き出している。
@if( $service['category'] === 'iphone' )
抜き出した配列のキー名category
の値がiphone
なら以下の処理を実行する。このように、
category
の値によって表示するタイトルとデータを変えている処理。
リファクタリング
1. 繰り返しのコードを別ファイルに移動する。
繰り返されているコードを別ファイルに記述する。ここでは、section.blade.phpを作成。
呼び出しは
@include
を使う。section.blade.php<section> <h2 class="c-page-headline">{{ $categoryTitle }}</h2> @foreach($services as $service) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endforeach </section>[1]
<h2 class="c-page-headline">{{ $categoryTitle }}</h2>
h2タグのデータは変数
$categoryTitle
とし、@include
した時に渡すようにする。
[2]@foreach($services as $service)
以前の処理@foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' )foreachでデータを一つづつ取得し、指定のカテゴリ名に一致する場合のみ実行(フィルタリング)していた処理を変更し、フィルタリング後のデータを
$services
として渡すようにする。
2. PHPの処理をコントローラに移動する
コントローラ(リファクタリング前)public function index(Request $request) { return view('contents.service.index'); }元の状態はビューファイルを返しているだけ。
コントローラ(リファクタリング後)public function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service; } } return view('contents.service.index', $services); }リファクタリング後はビューの中の
foreach
処理をコントローラ内で実行し、ビューに渡している。▼foreachの処理
foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service;・
if( isset($service['category']))
変数$serviceのキーcategoryに値があるか確認。・
$services[$service['category']][] = $service;
変数$services
を新たに用意。キー名がカテゴリー名となる連想配列にforeachで抜き出した値(
$service
)を追加していく。
▼注意点
配列に要素を追加する場合はarray[] = '追加する値'
とする。
array[キー名]
のようにキー名を指定して代入すると上書きになってしまう。
3. ビューの修正(
@include
で読み込む)切り出したビューを読み込む。
・
@include('ビュー', ['変数名'=>'渡すデータ'])
┗ ビューはresources > views 配下のディレクトリパスで指定。
┗ ディレクトリはドットでつなぐ。
┗ 第2変数でビューにデータを渡す。<div class="p-service__list"> @include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone]) @include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android]) @include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia]) </div>あんなに長かったビューが驚くほどシンプルになった。。
繰り返し処理があったら@include
が便利。
(補足)PHP処理のリファクタリングの考え方
リファクタリングLevel 0
リファクタリングなし
.blade.php@foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) //処理 @endif @endforeach @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'android' ) //処理 @endif @endforeach @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'xperia' ) //処理 @endif @endforeach↓ 処理を外部ファイルに移動し
@import
で読み込むPHP処理をビューファイルの情報に
リファクタリングLevel 1
.blade.php@php foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $iphone[] = $service; } elseif( isset($service['category']) && $service['category'] === 'android' ){ $android[] = $service; } elseif( isset($service['category']) && $service['category'] === 'xperia' ) $xperia[] = $service; } } @endphp <div class="p-service__list"> @include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone]) @include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android]) @include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia]) </div>↓ PHP処理をコントローラに移動
リファクタリングLevel 2
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $iphone[] = $service; } elseif( isset($service['category']) && $service['category'] === 'android' ){ $android[] = $service; } elseif( isset($service['category']) && $service['category'] === 'xperia' ) $xperia[] = $service; } } return view('contents.service.index', compact('iphone', 'android', 'xperia')); }ビューのPHP処理をそのままコントローラに移動。(★基本的に、PHP処理はビューではなくコントローラで行う)
・
compact('変数名', '変数名', '変数名',,,,,)
compactメソッドは指定した変数を連想配列にしてくれる。
キー名は変数名、値は変数に入っている値が自動的に適用される。※compactの注意点
変数は$変数名
ではなく、'変数名'
で渡す。↓ ビューに連想配列を渡す(compactメソッドを使わない)
リファクタリングLevel 3
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $services["iphone"][] = $service; } else if( isset($service['category']) && $service['category'] === 'android' ){ $services["android"][] = $service; } else if( isset($service['category']) && $service['category'] === 'xperia' ){ $services["xperia"][] = $service; } } return view('contents.service.index', $services); }・
$services["キー名"][] = 値
変数$services
を新たに定義し、指定したキーに値を追加していく。↓ カテゴリ名の分岐にifを使わない
リファクタリングLevel 4
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service; } } return view('contents.service.index', $services); }・
if( isset($service['category']))
ifを使うのは対象の値の存在確認のみ。・
$services[$service['category']][]
キー名はテキストでベタ打ちせず、$service['category'
で動的に指定する。
- 投稿日:2021-01-22T11:41:50+09:00
Laravel 8.x 時点での認証の実装
Laravel は多彩な認証ライブラリをリリースしています。
- Tailwind CSS && Blade Templates で出来た Laravel Breeze
- Tailwind CSS && (Livewire || Inertia) で出来た Laravel Jetstream
- OAuth 2 プロバイダ実装の Passport
- OAuth 2 ログイン実装の Socialite
- (レガシーパッケージとなっていますが) Bootstrap && (React || Vue) で出来た laravel UI
どれが要件に合うのかという所でもかなり悩みどころですが、とにかく選択肢は豊富です。
今回はこれらのライブラリについて深掘りしていくより、 Laravel 自体の認証の実装方法について調べてみます。
イントロダクション
Laravel Authenticationページでは、最初にこのように書かれています。
多くのウェブアプリケーションは、ユーザがアプリケーションで認証して「ログイン」するための方法を提供しています。この機能をウェブアプリケーションに実装することは、複雑でリスクを伴う可能性があります。このため、Laravelは、認証を素早く、安全に、簡単に実装するために必要なツールを提供するように努めています。
Laravelの認証機能は「ガード」と「プロバイダ」で構成されています。ガードは、各リクエストに対してユーザーがどのように認証されるかを定義します。例えば、Laravelにはセッションガードが搭載されており、セッションストレージとクッキーを使用して状態を維持します。
プロバイダーは、永続的なストレージからユーザーを取得する方法を定義します。LaravelはEloquentとデータベースクエリビルダを使ったユーザーの取得をサポートしています。しかし、アプリケーションに必要に応じて追加のプロバイダを自由に定義することができます。
アプリケーションの認証設定ファイルはconfig/auth.phpにあります。このファイルには、Laravelの認証サービスの動作を微調整するためのいくつかのオプションが含まれています。
www.DeepL.com/Translator (無料版)で翻訳しました。Config
認証情報の設定は
config/auth.php
にまとまっています。<?php return [ // デフォルト(Guard未指定)での利用 Guard(`Auth::user()` などした時に使われるもの) 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], // Guard の実装リスト。 Middleware の `auth:api` や `Auth::guard('api')` のように明示指定出来る 'guards' => [ 'web' => [ // SessionGuard を利用し、プロバイダは `users` (後述のキー値) 'driver' => 'session', 'provider' => 'users', ], 'api' => [ // TokenGuard を利用し、プロバイダは `users`, ハッシュ化はしない 'driver' => 'token', 'provider' => 'users', 'hash' => false, ], ], 'providers' => [ // 'users' プロバイダは Eloquent を利用する // 'users' というキー名は上記 Guard の 'provider' に指定するもの 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 代わりに DatabaseUserProvider を指定することも可能 // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], // ... 以下省略 ];Guard
どのリクエスト情報(session だとか Authorization ヘッダーだとか)からユーザ情報を取得出来るかの実装です。
<?php namespace Illuminate\Contracts\Auth; interface Guard { /** * 現在のユーザが認証されているかどうか * * @return bool */ public function check(); /** * 現在のユーザがゲスト(未ログイン)かどうか * * @return bool */ public function guest(); /** * 現在の認証されたユーザーを取得する * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user(); /** * 現在の認証されたユーザーの ID を取得する * * @return int|string|null */ public function id(); /** * ユーザーの秘匿情報をバリデートする * * @param array $credentials * @return bool */ public function validate(array $credentials = []); /** * 現在のユーザーを設定する * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function setUser(Authenticatable $user); }このインターフェースの実装となります。
これに対する Laravel 上での実装は
RequestGuard
,TokenGuard
,SessionGuard
の三つになります。RequestGuard
これは HTTP Request 内の任意の要素を使ってログイン判定をする最も簡単な Guard です。
Auth::viaRequest('custom-token', function (Request $request) { return User::where('token', $request->token)->first(); });このようにして新しいドライバーをクロージャで作ることが出来ます。
return [ 'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ], ];config/auth.php でこのようにドライバーを指定することで機能します。簡単。
これはステートレスなのでセッションを張らずに認証が可能です(代わりに毎回同じトークンを渡す必要があります)。
TokenGuard
これはリクエストからトークンを取得し、それをもって認証する Guard です。
- クエリストリング
/foo?api_token=aaa
- リクエストデータ
curl --data '{"api_token":"aaa"}'
- Bearer トークン
Authorization: Bearer aaa
- パスワード
https://foo:aaa@example.com
これらを探索し、トークンが見つかればそれを利用してログインを試みます。
api_token
というキー名は config で上書きが可能です。これもステートレスです。
SessionGuard
これはクッキーとストレージにセッション情報を残し、ステートフルに認証する Guard です。
普通にブラウザでアクセスする要件ではまずこれを使うのが基本になると思います。
UserProvider
Guard は「クライアントから送られてきた認証情報をどう取得するか」を定義したものに対し、 UserProvider は「取得した認証情報からデータベース内のユーザー情報をどう取得するか」を定義したものです。
<?php namespace Illuminate\Contracts\Auth; interface UserProvider { /** * ユニークIDでユーザーを取得する * * @param mixed $identifier * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveById($identifier); /** * ユニークIDと "remember me" トークンでユーザーを取得する * * @param mixed $identifier * @param string $token * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByToken($identifier, $token); /** * 渡されたユーザーの "remember me" トークンを更新する * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $token * @return void */ public function updateRememberToken(Authenticatable $user, $token); /** * 渡された秘匿情報からユーザーを取得する * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials); /** * 渡された秘匿情報を使ってユーザーをバリデートする * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(Authenticatable $user, array $credentials); }インターフェースはこのようになっています。
remember token が必須になっているのは若干モヤっとする設計ですが、基本的に渡されたパラメータでデータベースからユーザーを取得するメソッドを実装することになります。
Laravel では
EloquentUserProvider
とDatabaseUserProvider
が実装されています。EloquentUserProvider
最初からある
App\Models\User
クラスのような ORM を使って取得する手法です。最も一般的です。DatabaseUserProvider
コンフィグからテーブル名を指定して
password
カラムを使って取得する手法です。カラム名がpassword
固定なのがモヤっとするというか、使いづらい所ですね。
ちなみに
RequestGuard
を利用する場合はこの UserProvider を通さずにログインすることが出来ます(指定したクロージャで DB にアクセスしているので)。
この UserProvider で利用されるユーザー情報は
Illuminate\Contracts\Auth\Authenticatable
インターフェースを実装したクラスである必要があります(Eloquent である必要はありません)。<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { /** * ユーザーのユニークIDのカラム名を取得する * * @return string */ public function getAuthIdentifierName(); /** * ユーザーのユニークIDを取得する * * @return mixed */ public function getAuthIdentifier(); /** * ユーザーのパスワードを取得する * * @return string */ public function getAuthPassword(); /** * "remember me" セッション用のトークンを取得する * * @return string */ public function getRememberToken(); /** * "remember me" セッションのトークンを設定する * * @param string $value * @return void */ public function setRememberToken($value); /** * "remember me" トークンのカラム名を取得する * * @return string */ public function getRememberTokenName(); }またこの Authenticatable のデフォルト実装 trait として
Illuminate\Auth\Authenticatable
を利用することが出来ます。
- 投稿日:2021-01-22T11:01:15+09:00
LaravelでDBに保存した画像を表示する方法
はじめに
前回Laravelで画像のパスをDBに保存する方法をご紹介したので、今回は画像を表示する方法関してご紹介していきたいと思います。
保存する方法に関しては以下の記事をご参考ください。
Laravelで画像をアップロードし、パスをDBに保存する方法こちらでは、画像のパスがすでにDBに保存されている前提で進めており、ファイル名等は全て前回作成したものを利用していきます。
-各バージョン
-laravel 6.x
-PHP 7.4.9
-mySQL 5.7.30コントローラーを記述する
今回はindexアクションを使っていきたいと思います。
DBファザード使用するため、useで宣言し、そのあとに書いていきます。
BookControlleruse Illuminate\Support\Facades\DB; public function index() { $books = DB::table('books')->orderBy('created_at', 'desc')->get(); return view('index', compact('books')); }まず、前回作成したbooksテーブルのデータを取得し、
orderBy()
でcreated_at
、つまり作成した日時をdesc
順に並べるように指定しています。desc
とはdescendの略で、下に降りるという意味になるので、指定することによって作成した日時が新しいものが先頭に来るようになります。
そして取得したものを$books
という変数に格納しています。続いて格納したものを
return
でビューに渡すようにします。
index.blade.php
というビューをこのあと作成するので、index
を指定し、compact()
メソッドで変数をビューに渡すことができるようになっています。compact()
を使用するときは$マークはつけずに記述して問題ありません。また、今回はデータが少ないため全てのデータを取得していますが、もしデータが多く一覧画面では一部のデータのみ表示させたい場合は、以下のように書くこともできます。
BookControlleruse Illuminate\Support\Facades\DB; public function index() { $books = DB::table('books') ->select('id','title', 'author', 'created_at') //ここを追加 ->orderBy('created_at', 'desc') ->get(); return view('index', compact('books')); }
select()
でデータを選択することができるので、表示したいカラム名を指定することができます。
この場合は別途、全てのデータを表示する画面を作成するといいでしょう。ビューを作成する
新しくデータを表示するindex.blade.phpを作成し、一覧を表示させるコードを書いていきます。
なお、今回はデータが少ないので全てのデータが表示されるようにしていきます。index.blade.php@foreach('books' as 'book') <table> <tr> <th>タイトル</th><td>{{ $book->title }}</td> </tr> <tr> <th>作者</th><td>{{ $book->author }}</td> </tr> <tr> <th>投稿日</th><td>{{ $book->created_at }}</td> </tr> <tr> <th>画像</th><td><img src="{{ asset('uploads/books/' . $book->image) }}" alt="book-image"></td> </tr> </table> @endforeachBookControllerでbooksテーブルのデータを
$books
に格納しているので、データをforeach
で回して表示するようにしています。
画像に関しては、DBには画像のパスしか保存されていないため、画像の保存先を指定する必要があります。画像は前回Publicフォルダ内のuploads/booksに保存したので、今回はそのように指定しています。
また、見えやすくするようにtable
を使用しましたが、便宜に合わせてul
やp
タグで表示することも可能です。ルーティングを指定する
index.blade.phpに接続したら、BookController内のindexアクションが起動するようにします。
web.phpRoute::get('index', 'BookController@index')->name('index');以上で完成です!
さいごに
今回はDBに保存している画像のパスを表示させる方法に関して解説しました。
もっとこういうやり方あるよーという場合は、やさしくコメントで教えていただけるとありがたいです!
ここまで読んでくださりありがとうございました!参考