全体
サービスプロバイダ
サービスプロバイダーはサービスコンテナへサービス(インスタンス)を登録するためのもの。。
config/app.phpに使用するサービスプロバイダーが定義されている。
(登録はvendor/Illuminate\Foundation\Application.phpのregisterConfiguredProvidersメソッドで行われている)
サービスプロバイダーはphp artisan make:provider XxxServiceProvider
で作成することができる。
registerメソッドに$this->app->singleton(\Xxx\Yyy::class);
のようにサービス登録処理を記述し、bootメソッドにすべてのサービスプロバイダーが読み込まれたあとに実行したい処理を記述する。
ビューコンポーザはbootメソッドでView::composer()を実行することで、全てのサービスが実行された後、レンダリングの前に処理を実行させる仕組み。
- サービスコンテナへのサービスの登録
app()->bind(\Xxx\Yyy::class);
app()->singleton(\Xxx\Yyy::class); - サービスコンテナからサービスの取り出し
app()->make(\Xxx\Yyy::class);
ミドルウェア
指定したルートのアクションメソッドの前後に処理を実行させるための仕組み。
全アクションで実行させる場合はapp/Http/Kernel.phpに設定するが、それ以外はルート情報で設定する。
ミドルウェアを作成
php artisan make:middleware HelloMiddleware
handleメソッドに処理を追加
// アクション実行前
$request->merge(['msgFromHelloMiddleware' => 'hello from HelloMiddleware']);
// アクション実行
$response = $next($request);
// アクション実行後
$response->setContent(str_replace('置換されます', '置換されました', $response->content()));
return $response;
ルート情報にミドルウェアを追加する
// 個別のルートに追加する場合
Route::get('/', 'IndexController@index')->middleware(\App\Http\Middleware\HelloMiddleware::class);
// ルート情報のgroupメソッドの第1引数で指定することもできる。
Route::group(['middleware' => ['Hello']], ]function() {
Route::get('hoge', 'HogeController@index');
});
// 全アクションで実行させる場合はグローバルミドルウェアとして登録する
// app/Http/Kernel.phpの$middleware配列に追加する。
// ミドルウェアグループとして登録する場合
Route::get('/', 'IndexController@index')->middleware('hello');
// app/Http/Kernel.phpの$middlewareGroups連想配列に追加しておく必要がある
// 'hello' => [
// \App\Http\Middleware\HelloMiddleware::class,
// ],
バリデーション
バリデーションはコントローラ・モデル・フォームリクエストに定義することができる。
コントローラに定義する場合
コントローラのvalidateメソッドを使う
$this->validate($request, ['name' => 'required', 'max:10']);
validateメソッドはControllerクラスに組み込まれているValidatesRequestsというトレイト(メンバーをまとめてクラスに追加する仕組み)により提供されているメソッド。
※ エラーがあった場合は自動的に前の画面にリダイレクトされる
Viewでの表示
@foreach ($errors as $error)
<p class="text-danger">{{ $error }}</p>
@endforeach
@if ($errors->has('msg'))
<p class="text-danger">{{ $errors->first('msg') }}</p>
@endif
モデルに定義する場合
モデルにfillableとrulesプロパティを定義
protected $fillable = ['name'];
public static $rules = [
'name' => 'required|string|max:10'
];
fillableによるホワイトリスト指定ではなくguardedによるブラックリスト指定も可能だが、fillableを使う方が無難。
- fillableの場合
allメソッドでフォーム変数を全てfillメソッドに渡すことができる。$item->fill($request->all())->save();
- guardedの場合
onlyメソッドやexceptメソッドで必要な項目を絞り込む必要がある。$item->fill($request->except('_token'))->save();
$item->fill($request->only(['name', 'password']))->save();
フォームリクエストに定義する場合
コントローラのvalidateメソッドは自分で呼び出さなければならない。
フォームリクエストの場合、呼び出しは不要。
エラーがあった場合に自動的に前の画面にリダイレクトされる点や、Viewでの表示方法はvalidateメソッドと同じ。
フォームリクエストを作成
php artisan make:request HelloRequest
作成されたHelloRequestクラスにはauthorizeメソッドとruleメソッドが用意されている。
authorizeメソッドは認証をチェックするためのもので、特にやることがない場合はreturn true;
でOK。
HelloRequest.phpのruleメソッドでルール配列を返却
public function rules()
{
return ['msg' => ['required', 'max:10']];
}
messagesメソッドをオーバーライドすることでエラーメッセージ を変更することができる
public function messages()
{
return [
'msg2.required' =>'メッセージ2は必須です。'
];
}
独自バリデータ
「エラー時にリダイレクトさせたくない」「フォームに値以外をチェックしたい」場合などは、Validator::make()
で独自バリデータを生成して使用する。
$validator = Validator::make($request->all(), ['name' => 'required'], ['name.required' => '名前が入力されていません']);
if ($validator->fails()) {
return redirect('/hello')->withErrors($validator)->withInput();
}
ユーザー認証
Laravel 5.8 までは、php artisan make:auth
だけでログイン機能を実装できたが、 Laravel 6.0 から手順が変わった。
php artisan migrate
でusersテーブル、password_resetsテーブルが作成される。
※ Laravelインストール時にマイグレーションファイル、コントローラ(App\Http\Controllers\Auth)は作成されている。
composer require laravel/ui:^1.0 --dev
php artisan ui bootstrap --auth
またはphp artisan ui vue --auth
※ laravel/uiのバージョンはLaravelのバージョンで異なる。
https://laravel.com/docs/6.x/frontend#introduction
https://laravel.com/docs/7.x/frontend#introduction
データベース
クエリビルダ
DB::table('テーブル名');
でBuilderインスタンスを取得することができる
DB::table('users')->get();
戻り値はstdClassのCollectionDB::table('users')->first();
戻り値はstdClass
Builderインスタンスのwhere, orWhere, whereRaw, orderBy, offset, limitなどのメソッドでSQLを組み立てる。
get, first, insert, update,deleteなどのメソッドでSQLを実行する。
モデル(Eloquent)
Task::orderBy('id', 'desc')
のようにモデルのクラスメソッドを使ってBuilderインスタンスを取得する。
モデルはクエリビルダのインスタンスメソッドに相当する(同じメソッド名の)クラスメソッドを持っている。
DBクラスから取得したクエリビルダはIlluminate\Database\Query\Builderだが、モデルから取得したクエリビルダはIlluminate\Database\Eloquent\Builderである。
そのため、モデルから取得したBuilderインスタンスの場合、取得したデータの型はモデルとなる。
(DBクラスの場合はstdClass)
Task::get();
戻り値はTaskのCollectionTask::first();
戻り値はTask
データの取得
クラスメソッドall, findを使う、またはwhereやorderByなどのクラスメソッドでBuilderインスタンスを取得してからgetまたはfirstメソッドを実行する。
Task::all();
Task::where('name', 'hoge')->get();
データの登録・更新・削除
登録・更新はモデルのsaveメソッド、削除はdeleteメソッドを使う。
// 登録
$task = new Task();
$task->name = 'hoge';
$task->save();
// 更新
$task = Task::find(1);
$task->name = 'hoge';
$task->save();
// 削除
$task = Task::find(1);
$task->delete();
hasメソッド, dosentHaveメソッド
hasOne, hasMany, belongsToでリレーションを定義した場合、hasメソッド, dosentHaveメソッドで関連レコードが存在する(しない)データだけを取得することができる。
whereHas, orWhereHasメソッドで条件を指定することもでき、joinメソッドを使うよりも簡単な記述が可能となる。
User::has('tasks')->get();
User::dosentHave('tasks')->get();
User::whereHas('tasks', function (Builder $query) {
$query->where('title', 'like', '%hoge%');
})->get();
Eagerロード
N+1問題を回避することができる。
例えば、usersテーブルとtasksテーブルがhasManyの関係である場合、User::all()
とすると、まずUserが全て取得され、その後Postが1つずつ取得される。
よって、postsが100件あった場合は101回クエリが実行されてしまう。 User::with('tasks')->get();
とすると内部でWHERE INが使われるためクエリは2回しか実行されない。
ページネーション
クエリビルダインスタンスのpagenateメソッド、simplePagenateメソッドを使う。$tasks = Task::where('id', '>', 100)->pagenate(10);
ビューでは{{ $tasks->links() }}
のようにする。
パラメータを引き継ぐ場合はappends()メソッドを使って{{ $tasks->appends(['name'=>$name])->links() }}
のようにする。
コメント