LaravelのRequestを使ったForm ValidateにRequestクラス内共通の処理を使いたかった
つまり、Requestのメソッドを使いたかったんだけど、それはできないみたいなのでクロージャを使った。
<?php class UserRequest extends FormRequest { public function rules() { // 共通で処理するValidator $my_validate = function($attribute, $value, $fail){ return $fail('no good'); }; $rules = [ 'name' => [ 'required', $my_validate,
こんな感じ。
requiredを満たした時、この$my_validateが走る。
LaravelでPolicyを追加する時に、ModelがInjectionしてくれなくて困った件
この辺りを読んでて… readouble.com
<?php Route::post('user/confirm', 'UserController@confirm')->name('user.create.confirm')->middleware('can:confirm,App\User'); Route::post('user/{user}/confirm', 'UserController@confirm')->name('user.update.confirm')->middleware('can:confirm,App\User');
って書いて、UserPolicyのcnofirmメソッドに
<?php public function confirm(User $user, User $model = null) {
って書いたけど、$modelにObjectあきよらん…って思ってたけど、
createのようなアクションではモデルインスタンスを必要としません。このようなケースでは、ミドルウェアへクラス名を渡してください。クラス名はアクションを認可するときに、どのポリシーを使用するかの判断に使われます。
とあって、->middleware()の第二引数(正確には第一引数のカンマ区切り2個目)にクラスを書くのはmodelが不要なときだった…
$modelが必要な場合は
canミドルウェアへ2つの引数を渡しています。最初の引数は認可したいアクションの名前です。2つ目はポリシーメソッドに渡したいルートパラメータです。
とあるように、Routeで{user}としたものが入るので↑のRouteの記述は
<?php Route::post('user/confirm', 'UserController@confirm')->name('user.create.confirm')->middleware('can:confirm,App\User'); Route::post('user/{user}/confirm', 'UserController@confirm')->name('user.update.confirm')->middleware('can:confirm,user');
とやるのが正解。
LaravelでSQLログを出力するのをProviderで実装する
以前書いたコレ。
Providerで実装する。
Providerを作る
こちらを参考に。 qiita.com
app/Providers/DataBaseQueryServiceProvider.php
<?php declare(strict_types=1); namespace App\Providers; use Carbon\Carbon; use DateTime; use DB; use Event; use Illuminate\Database\Events\TransactionBeginning; use Illuminate\Database\Events\TransactionCommitted; use Illuminate\Database\Events\TransactionRolledBack; use Illuminate\Support\ServiceProvider; use Log; class DataBaseQueryServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register(): void { if (env('APP_SQL_DEBUG') !== true) { return; } DB::listen(function ($query) { $sql = $query->sql; foreach ($query->bindings as $binding) { if (is_string($binding)) { $binding = "'{$binding}'"; } elseif (is_bool($binding)) { $binding = $binding ? '1' : '0'; } elseif ($binding === null) { $binding = 'NULL'; } elseif ($binding instanceof Carbon) { $binding = "'{$binding->toDateTimeString()}'"; } elseif ($binding instanceof DateTime) { $binding = "'{$binding->format('Y-m-d H:i:s')}'"; } $sql = preg_replace("/\?/", $binding, $sql, 1); } Log::channel('sqllog')->debug('SQL', ['sql' => $sql, 'time' => "$query->time ms"]); }); Event::listen(TransactionBeginning::class, function (TransactionBeginning $event) { Log::channel('sqllog')->debug('START TRANSACTION'); }); Event::listen(TransactionCommitted::class, function (TransactionCommitted $event) { Log::channel('sqllog')->debug('COMMIT'); }); Event::listen(TransactionRolledBack::class, function (TransactionRolledBack $event) { Log::channel('sqllog')->debug('ROLLBACK'); }); } }
Providerを登録する
config/app.php
<?php 'providers' => [ ...略 /* * Package Service Providers... */ /* * Application Service Providers... */ App\Providers\DataBaseQueryServiceProvider::class,
loggerを登録する
config/logging.php
<?php 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], 'sqllog' => [ 'driver' => 'daily', 'path' => storage_path('logs/sql.log'), 'level' => 'debug', ],
LaravelのAuthをAPIで効かす時にいつも忘れるのでデジタルタトゥーに刻みたい
make authしてから
$ ./artisan make:auth
は、Laravelの古い奴だっけ…
じゃなくて
$./artisan ui vue --auth
してから、
APIでもSessionを効かす
app/Http/Kernel に
<?php protected $middlewareGroups = [ 'web' => [ // 省略 ], 'api' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class,
この4行を追加する。
Policyを効かす
$ ./artisan make:policy UserPolicy --model=User
とかでModelのPolicyを作って、Controllerで
<?php class UserController extends Controller { /** * CardInfoController constructor. */ public function __construct() { $this->authorizeResource(User::class, 'user'); }
とかするとリソースポリシーが効く