- 投稿日:2019-10-09T15:18:46+09:00
【Laravel】管理画面と一般サイトでログファイルを分けてみる
一般ユーザがアクセスする画面と、管理者がアクセスする画面があるサイトの場合、一つのログに出力していると、両方のログが混在して「これはどっちの処理のログ?」みたいになって分かりづらい。
- 一般ユーザは、一般ユーザ用のログファイルに出力
- 管理者は、管理者用のログファイルに出力
という風に完全に分けられれば見やすくなるはず。
さっそく分けてみた。
環境
- laravel 5.8
前提
一般ユーザ用の画面
「https://example.com/admin」配下以外は全部、一般ユーザ用
管理画面
逆に「https://example.com/admin」配下は全部、管理画面
作ってみた
Larvael5.6からログの設定方法・出力方法が大きく変わった様で、今回は5.8で試しています。(検証はしてないけど、たぶん5.6〜5.7でも動くのではないかと。)
ざっくりとした手順
- 一般ユーザ用と管理者用のログチャネルを作成
- ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する
- 自作ファサードの登録
一般ユーザ用と管理者用のログチャネルを作成
ログ設定用のコンフィグファイルに設定を追加します。
admin
チャネルとuser
チャネルを追加し、それぞれ出力先ファイルを指定する。/config/logging.php'channels' => [ /** * * 元々書いてある設定は省略 * */ //以降を追加 'admin' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel_admin.log'), 'level' => env('LOGGING_LEVEL', 'info'), 'days' => env('LOG_ROTATE_DAYS', 14), ], 'user' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel_user.log'), 'level' => env('LOGGING_LEVEL', 'info'), 'days' => env('LOG_ROTATE_DAYS', 14), ], ],ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する
ファサードクラス
公式の手順通りに作成
/app/Facades/CustomLogFacade.php<?php namespace App\Facades; use App\Services\Support\CustomLogSupport; use Illuminate\Support\Facades\Facade; class CustomLogFacade extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return CustomLogSupport::class; } }ロジッククラス
ファサードの本体を作成します。
/app/Service/Support/CustomLogSupport.php<?php namespace App\Services\Support; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request; use Illuminate\Support\Str; class CustomLogSupport { public function __call($name, $args) { $chanel = 'stack'; try{ $domain = config('app.url'); $url = Request::url(); if(Str::is($domain.'/admin/*', $url)){ $chanel = 'admin'; }else if(Str::is($domain.'/*', $url)){ $chanel = 'user'; }else{ $chanel = 'batch'; } }catch (\Exception $e){ //握りつぶす } $collectArgs = collect($args); Log::channel($chanel)->{$name}($collectArgs->shift(), $collectArgs->toArray()); } }マジックメソッドの
__call()
を使って、Log
ファサードをラップしてます。
その際にchannel($chanel)
で使用するチャネルを指定しています。このチャネル振り分けロジックを変えればサブドメイン毎にログを分ける事もできそうです。
自作ファサードの登録
これもお決まり通りに登録します。
サービスコンテナに登録
/app/Providers/AppServiceProvider.phppublic function register() { //ログ出力 $this->app->singleton(CustomLogSupport::class, CustomLogSupport::class); }ファサードの登録
/app/config/app.php'aliases' => [ /** * * 元々書いてある設定は省略 * */ 'CustomLog' => \App\Facades\CustomLogFacade::class, ],結果
$ ls laravel_admin-2019-10-09.log laravel_user-2019-10-09.log分割して出力された!
ちなみにファサードの実態クラス(今回でいうと
CustomLogSupport
)ってどういうクラス名で、どういうディレクトリに格納するのが一般的なんですかね?
- 投稿日:2019-10-09T15:18:46+09:00
【Laravel】ログファイルを機能ごとに分けてみる
一般ユーザがアクセスする画面と、管理者がアクセスする画面があるサイトの場合、一つのログに出力していると、両方のログが混在して「これはどっちの処理のログ?」みたいになって分かりづらい。
- 一般ユーザは、一般ユーザ用のログファイルに出力
- 管理者は、管理者用のログファイルに出力
という風に完全に分けられれば見やすくなるはず。
さっそく分けてみた。
環境
- laravel 5.8
前提
一般ユーザ用の画面
「https://example.com/admin」配下以外は全部、一般ユーザ用
管理画面
逆に「https://example.com/admin」配下は全部、管理画面
作ってみた
Larvael5.6からログの設定方法・出力方法が大きく変わった様で、今回は5.8で試しています。(検証はしてないけど、たぶん5.6〜5.7でも動くのではないかと。)
ざっくりとした手順
- 一般ユーザ用と管理者用のログチャネルを作成
- ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する
- 自作ファサードの登録
一般ユーザ用と管理者用のログチャネルを作成
ログ設定用のコンフィグファイルに設定を追加します。
admin
チャネルとuser
チャネルを追加し、それぞれ出力先ファイルを指定する。/config/logging.php'channels' => [ /** * * 元々書いてある設定は省略 * */ //以降を追加 'admin' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel_admin.log'), 'level' => env('LOGGING_LEVEL', 'info'), 'days' => env('LOG_ROTATE_DAYS', 14), ], 'user' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel_user.log'), 'level' => env('LOGGING_LEVEL', 'info'), 'days' => env('LOG_ROTATE_DAYS', 14), ], ],ログ出力用の自作ファサードを作成し、そこでログチャネルを指定する
ファサードクラス
公式の手順通りに作成
/app/Facades/CustomLogFacade.php<?php namespace App\Facades; use App\Services\Support\CustomLogSupport; use Illuminate\Support\Facades\Facade; class CustomLogFacade extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return CustomLogSupport::class; } }ロジッククラス
ファサードの本体を作成します。
/app/Service/Support/CustomLogSupport.php<?php namespace App\Services\Support; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request; use Illuminate\Support\Str; class CustomLogSupport { public function __call($name, $args) { $chanel = 'stack'; try{ $domain = config('app.url'); $url = Request::url(); if(Str::is($domain.'/admin/*', $url)){ $chanel = 'admin'; }else if(Str::is($domain.'/*', $url)){ $chanel = 'user'; }else{ $chanel = 'batch'; } }catch (\Exception $e){ //握りつぶす } $collectArgs = collect($args); Log::channel($chanel)->{$name}($collectArgs->shift(), $collectArgs->toArray()); } }マジックメソッドの
__call()
を使って、Log
ファサードをラップしてます。
その際にchannel($chanel)
で使用するチャネルを指定しています。このチャネル振り分けロジックを変えればサブドメイン毎にログを分ける事もできそうです。
自作ファサードの登録
これもお決まり通りに登録します。
サービスコンテナに登録
/app/Providers/AppServiceProvider.phppublic function register() { //ログ出力 $this->app->singleton(CustomLogSupport::class, CustomLogSupport::class); }ファサードの登録
/app/config/app.php'aliases' => [ /** * * 元々書いてある設定は省略 * */ 'CustomLog' => \App\Facades\CustomLogFacade::class, ],結果
$ ls laravel_admin-2019-10-09.log laravel_user-2019-10-09.log分割して出力された!
ちなみにファサードの実態クラス(今回でいうと
CustomLogSupport
)ってどういうクラス名で、どういうディレクトリに格納するのが一般的なんですかね?
- 投稿日:2019-10-09T14:02:21+09:00
Laravel bladeから静的ページを生成して表示速度を改善してみたい
概要
- bladeから静的ページを生成しそのページを表示する
- データの更新時には一緒に更新する
という運用をやってみようという記事
手順例
HTMLファイル生成するイベントを作る
こんな感じのことをするイベントを作成する。
記事ページなどの単一のモデルのデータしか使わない場合は、Modelに定義するとよさそうです。public function __construct(User $user) { $html = view('home.home')->with('user', $user)->render(); // htmlファイルの保存場所は任意 file_put_contents(storage_path("app/public/home.html"), $html); }イベントを発火
作ったイベントをModelの$dispatchesEventsに定義したりなどして、更新時に動くようにする。
後はコマンドにしたり。ルーティング
例えば
Route::get('/', function () { // \Illuminate\Support\Facades\File return \File::get('storage/home.html'); });備考
- 必要ならばファイルを削除するイベントも作って、削除時に発火させる
- HTMLファイルが無かったら通常通りbladeを表示するようにすると、安心する
- ビューにControllerやMiddlewareからデータを渡しているとレンダーされる時に読み込まれないので、ViewComposerで定義すると嬉しい
おわり
記事ページ等はbladeの更新の際に全HTMLファイルを更新する必要が出てくるので、向かないかもしれません。
運用には注意が必要ですが、bladeの更新頻度が低いかつ表示速度が遅いページの改善法として有効だと思います。TOPページなど。
- 投稿日:2019-10-09T10:44:29+09:00
Laravelのミューテタはfillableに設定できるか
タイトル通り。
結論としては使えます。
※Laravel:6.0.3
サンプル
class User extends Model { protected $fillable = [ 'name', 'age' ] }>>> App\User::create(["name" => "hoge", "age" => 99]) => App\User { id: 1, name: "hoge", age: 99, updated_at: "2019-10-09 10:20:33", created_at: "2019-10-09 10:20:33", }ミューテタを追加
class User extends Model { protected $fillable = [ 'name', 'age', 'birthday' ] public function setBirthdayAttribute($value) { $this->attributes['age'] = CarbonImmutable::parse($value)->age; } }birthdayの方で作ってみる
>>> App\User::create(["name" => "fuga", "birthday" => "2000-04-01"]) => App\User { id: 2, name: "fuga", age: 19, updated_at: "2019-10-09 10:35:48", created_at: "2019-10-09 10:35:48", }fillableに残っているのでageもそのまま使える
>>> App\User::create(["name" => "piyo", "age" => 50]) => App\User { id: 3, name: "piyo", age: 50, updated_at: "2019-10-09 10:36:01", created_at: "2019-10-09 10:36:01", }birthdayで必ず作りたいならfillableからageを外してしまえばokです。
- 投稿日:2019-10-09T09:58:16+09:00
Laravel Telescopeをアンインストールする
config/app.phpから
TelescopeServiceProvider
を削除app.phpApp\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\TelescopeServiceProvider::class,//←これ App\Providers\RouteServiceProvider::class,composerの依存関係からも削除する場合
composer remove laravel/telescope
を実行する削除せずに無効にしたい場合
composer.json"extra": { "laravel": { "dont-discover": ["laravel/telescope"] } },
composer dump
で再ロード