Laravel のミドルウェアを使って操作のログを自動で記録してみます
操作ログはデータベースへ保存して、ログイン済みであればユーザIDも自動で記録
記録した操作ログを一覧表示する画面も作成しときます
#ログテーブル作成
まずは操作(アクション)ログを記録するテーブルを作成します
php artisan make:migration create_actlogs_table --create=actlogs
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateActlogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('actlogs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id') -> unsigned() -> nullable() -> comment("ユーザID");
$table->string('route') -> nullable() -> comment("route.webで設定した名称");
$table->string('url') -> nullable() -> comment("要求Path");
$table->string('method') -> nullable() -> comment("要求メソッド Get Post");
$table->integer('status') -> unsigned() -> nullable() -> comment("要求結果 200 OK とか 301 move 等");
$table->text('data') -> nullable() -> comment("要求内容(暗号化して保存)");
$table->string('remote_addr') -> nullable() -> comment("クライアントIPアドレス");
$table->string('user_agent') -> nullable() -> comment("ブラウザ名");
$table->timestamps();
$table->index(['created_at']);
$table->index(['user_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('actlogs');
}
}
ログに記録するのは以下
・ユーザID
・ページ名(routes/web.php の name でつけといた名前)
・要求パス
・要求メソッド(GETとかPOSTとか)
・要求結果 200 OK とか 301 Move とか
・要求内容(あれば)
・接続元 IPアドレス
・ブラウザ名(UserAgent)
・作成時間(DB記録時間)
定義から実テーブルの作成もしときます
php artisan migrate:refresh --seed
#テーブルに対応するモデルも作成
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Crypt;
class Actlog extends Model
{
// 更新日時記録無効化
const UPDATED_AT = null;
// Jsonに追加で含める
protected $appends = ['name'];
// ユーザの氏名を取得 -- リレーションできなかった場合は空文字を返す
public function getNameAttribute()
{
$user = $this -> user;
if ($user) return $user -> name;
else return '';
}
// カラム暗号化 - 要求内容は暗号化して保存する
public function setDataAttribute($value)
{
if ($value) {
$this->attributes['data'] = Crypt::encrypt( serialize($value) );
}
}
// カラム複合化 - 要求内容を取り出すときに複合化する
public function getDataAttribute($value)
{
if ($value) {
return unserialize( Crypt::decrypt($value) );
} else {
return $value;
}
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'user_id',
'route',
'url',
'method',
'status',
'data',
'remote_addr',
'user_agent',
];
// Json に出力する項目
protected $visible = [
'user_id',
'route',
'url',
'method',
'status',
'data',
'remote_addr',
'user_agent',
'created_at',
'name',
];
public function user()
{
return $this -> belongsTo('App\User', 'user_id', 'id');
}
}
通信内容( 'data' )は暗号化して保存
あと、UPDATEはしないので記録しないように設定しときます
一覧で見やすいようにユーザ名( 'name' )も返すようにしてあります
#ミドルウェア作成
実際にログを記録するミドルウェアを作成です
$ php artisan make:middleware ActlogMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
use App\Actlog;
use \Route;
class ActlogMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$this->actlog($request, $response -> getStatusCode());
return $response;
}
public function actlog($request, $status)
{
$user = $request -> user();
$data = [
'user_id' => $user ? $user->id : null,
'route' => Route::currentRouteName(),
'url' => $request -> path(),
'method' => $request -> method(),
'status' => $status,
'data' => count($request->toArray()) != 0 ? json_encode($request->toArray()) : null,
'remote_addr' => $request -> ip(),
'user_agent' => $request -> userAgent(),
];
Actlog::create($data);
}
}
ルーティング情報を取得するために Route を利用してます
ログインユーザは$request -> user() から取得
要求内容( 'data' )はJson形式で保存しときます
#ミドルウェア登録
protected $middleware = [
~~~~
★ \App\Http\Middleware\ActlogMiddleware::class,
];
~~~~
$middleware の中に追加すると グローバルとして必ず呼ばれるミドルウェアとして登録されるみたいです
詳しくはこちら
https://readouble.com/laravel/5.6/ja/middleware.html
ログアウト対応
このミドルウェアの実行タイミングは各処理が「終わった後」になるので「誰」がログアウトしたのか操作者のIDが記録できません
なのでログアウトの実行前にログを記録するようにしておきます
ログアウトを実際に行うのは 「 vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php 」のようなので
ログアウト操作をこっち「 app/Http/Controllers/Auth/LoginController.php 」で上書きしてやります
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
~~~~~~~~
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$actlog = new \App\Http\Middleware\ActlogMiddleware;
$actlog -> actlog($request, 999);
$this->guard()->logout();
$request->session()->invalidate();
return $this->loggedOut($request) ?: redirect('/');
}
}
実際にログアウトを実行する「$this->guard()->logout();」前に、actlogを記録してやります
見分けやすいようにステータスを 「999」で記録しときます
#動作確認
##1)DBに接続してテーブル定義とテーブル内容を確認
mysql -u lara_user -p lara
mysql> desc actlogs;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(10) unsigned | YES | MUL | NULL | |
| route | varchar(255) | YES | | NULL | |
| url | varchar(255) | YES | | NULL | |
| method | varchar(255) | YES | | NULL | |
| status | int(10) unsigned | YES | | NULL | |
| data | text | YES | | NULL | |
| remote_addr | varchar(255) | YES | | NULL | |
| user_agent | varchar(255) | YES | | NULL | |
| created_at | timestamp | YES | MUL | NULL | |
| updated_at | timestamp | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
mysql> SELECT * FROM actlogs;
Empty set (0.00 sec)
##2)ログイン画面表示
ブラウザでログイン画面を開きます
mysql> SELECT * FROM actlogs;
+----+---------+------------+-------+--------+--------+------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| id | user_id | route | url | method | status | data | remote_addr | user_agent | created_at | updated_at |
+----+---------+------------+-------+--------+--------+------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| 1 | NULL | NULL | / | GET | 302 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
| 2 | NULL | login.show | login | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
+----+---------+------------+-------+--------+--------+------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
2 rows in set (0.01 sec)
最初 / にアクセスして 302で遷移
ログイン画面(login.show)を表示したログが記録されてます
##3)ログイン実行
ブラウザでログイン操作
+----+---------+------------+-------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| id | user_id | route | url | method | status | data | remote_addr | user_agent | created_at | updated_at |
+----+---------+------------+-------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| 1 | NULL | NULL | / | GET | 302 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
| 2 | NULL | login.show | login | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
| 3 | 1 | login | login | POST | 302 | eyJpdiI6IjVmNE5UZ2ExSUw2QWYrTVh6ZUpqRnc9PSIsInZhbHVlZTRjYzAwZGI0NCJ9 | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:44:28 | NULL |
| 4 | 1 | NULL | / | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:44:28 | NULL |
+----+---------+------------+-------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
4 rows in set (0.00 sec)
id:3 の行でログイン後、
id:4 / に行って Vue の画面を表示してます( routes/web.php で指定 )
要求内容もちゃんと暗号化されているようです
ユーザIDも記録されてますね
##4)ページ遷移
別記事で作成済みの「社員一覧」ページを開いてみます
mysql> SELECT * FROM actlogs;
+----+---------+------------------+----------------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| id | user_id | route | url | method | status | data | remote_addr | user_agent | created_at | updated_at |
+----+---------+------------------+----------------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
| 1 | NULL | NULL | / | GET | 302 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
| 2 | NULL | login.show | login | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:42:45 | NULL |
| 3 | 1 | login | login | POST | 302 | eyJpdiI6IjVmNE5UZ2UxOWRhMzhjNDdiN2I4NTAxNDcwMDZlODVlZTRjYzAwZGI0NCJ9 | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:44:28 | NULL |
| 4 | 1 | NULL | / | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:44:28 | NULL |
| 5 | 1 | admin.user.index | api/admin/user | POST | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:47:39 | NULL |
+----+---------+------------------+----------------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
id:5 でadmin.user.index ページを開いたログが記録されてます
##5)ログアウト
ログアウト操作をしてみます
| 5 | 1 | admin.user.index | api/admin/user | POST | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:47:39 | NULL |
| 6 | 1 | logout | logout | POST | 999 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:50:28 | NULL |
| 7 | NULL | logout | logout | POST | 302 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:50:28 | NULL |
| 8 | NULL | NULL | / | GET | 401 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:50:28 | NULL |
| 9 | NULL | NULL | / | GET | 302 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:50:28 | NULL |
| 10 | NULL | login.show | login | GET | 200 | NULL | 172.16.0.1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36 | 2019-02-08 07:50:28 | NULL |
+----+---------+------------------+----------------+--------+--------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+---------------------+------------+
10 rows in set (0.00 sec)
id:6 で実際のログアウト処理の前にログアウトを記録(999)して
id:7 で実際にログアウト
id:8 で 401(未認証)だから / に行って
id:9 で / から 302 でリダイレクトして
id:10 で ログイン画面を表示
ってことになってますね
ちゃんと操作のログが記録されているようです
Vue 操作ログの一覧画面
ログ記録の確認が取れたので、画面側も作っておきます
<template>
<v-flex>
<v-card xs12 class="m-3 px-3">
<v-card-title class="title">
<v-icon class="pr-2">{{ $route.meta.icon }}</v-icon> {{ $route.meta.name }} {{ /* 操作ログ */ }}
<v-spacer></v-spacer>
<v-spacer></v-spacer>
<v-text-field
v-model="search"
prepend-icon="search"
label="Search"
single-line
hide-details
clearable
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="tabledata"
:pagination.sync="pagination"
:rows-per-page-items='[10,25,50,{"text":"All","value":-1}]'
:loading="loading"
:search="search"
class="elevation-0 p-1"
>
<v-progress-linear slot="progress" color="blue" indeterminate></v-progress-linear>
<template slot="items" slot-scope="props">
<tr>
<td class="text-xs-center" xs1>{{ (props.index + 1) + (pagination.page - 1) * pagination.rowsPerPage }}</td>
<template v-for="n in (headers.length - 1)">
<td :class="'text-xs-' + headers[n].align" style="white-space: nowrap;" v-text="props.item[headers[n].value]"></td>
</template>
</tr>
</template>
</v-data-table>
<v-spacer></v-spacer>
<v-card-actions>
<csv-download url="/api/admin/actlog/download" color="primary" @axios-logout="$emit('axios-logout')"></csv-download>
</v-card-actions>
</v-card>
</v-flex>
</template>
<script>
import csv_download from './CsvDownload.vue'
export default {
name: 'ActlogComponent',
components: {
'csv-download': csv_download,
},
props: {
},
data: () => ({
loading: false,
search: '',
pagination: { sortBy: 'created_at', descending: true, },
tabledata: [],
headers: [
{ align: 'center', sortable: false, text: 'No', },
{ align: 'left', sortable: true, text: '日時', value: 'created_at' },
{ align: 'left', sortable: true, text: '氏名', value: 'name' },
{ align: 'left', sortable: true, text: '操作', value: 'action' },
{ align: 'center', sortable: true, text: '結果', value: 'status' },
{ align: 'left', sortable: true, text: 'データ', value: 'data' },
{ align: 'left', sortable: true, text: 'IP', value: 'remote_addr' },
{ align: 'left', sortable: true, text: 'UA', value: 'user_agent' },
],
}),
created() {
if (process.env.MIX_DEBUG) console.log('Actlog Component created.')
this.initialize()
},
methods: {
initialize() {
this.getData()
},
getData() {
if (process.env.MIX_DEBUG) console.log('Actlog Component getData')
this.loading = true
axios.post('/api/admin/actlog')
.then( function (response) {
this.loading = false
if (process.env.MIX_DEBUG) console.log(response)
if (response.data.data) {
this.tabledata = this.setAction(response.data.data)
}
}.bind(this))
.catch(function (error) {
this.loading = false
console.log(error)
if (error.response && [401, 419].includes(error.response.status)) {
this.$emit('axios-logout')
}
}.bind(this))
},
setAction(data) {
if (process.env.MIX_DEBUG) console.log('Actlog Component setAction')
var wk = ''
for (let i=0; i<data.length; i++) {
switch (data[i].route) {
// Login - Logout
case 'show.login' : wk = 'ログイン画面'; break;
case 'login' : wk = 'ログイン'; break;
case 'logout' : wk = 'ログアウト'; break;
// USER
case 'admin.user.index' : wk = '社員一覧'; break;
case 'admin.user.store' : wk = '社員追加'; break;
case 'admin.user.destroy' : wk = '社員削除'; break;
case 'admin.user.download' : wk = '社員CSV_DL'; break;
case 'admin.user.upload' : wk = '社員CSV_UP'; break;
// OTHER
default: wk = data[i].route
}
data[i].action = wk
}
return data
},
},
}
</script>
一覧を取ってきて、route名をわかりやすい日本語にして表示
ってことをしています
操作履歴はデータ量が多そうなので、取得範囲やら「誰」やらの検索条件指定などもそのうち追加しなくちゃですかね
Vue ナビゲーション追加
ページを追加したのでナビゲーションも追加しときます
まずは定義ファイル
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
//
import example_component from '../components/ExampleComponent.vue'
import admin_component from '../components/AdminComponent.vue'
import r_link from '../components/RouterLink.vue'
//
Vue.component('example-component', example_component)
Vue.component('admin-component', admin_component)
Vue.component('r-link', r_link)
//
import home from '../components/HomeComponent.vue'
import admin_user from '../components/Admin/UserComponent.vue'
import admin_payslip from '../components/Admin/PayslipComponent.vue'
★ import admin_actlog from '../components/Admin/ActlogComponent.vue'
export default new Router({
mode: 'history',
routes: [
{ path: '/admin/user', name: 'admin_user', component: admin_user, meta: {name: '社員管理', icon: 'supervisor_account'}},
{ path: '/home', name: 'home', component: home, meta: {name: 'ホーム', icon: 'home'}},
{ path: '/admin/payslip',name: 'admin_payslip', component: admin_payslip, meta: {name: '給与明細', icon: 'fa-file-invoice-dollar'}},
★ { path: '/admin/actlog', name: 'admin_actlog', component: admin_actlog, meta: {name: '操作履歴', icon: 'list'}},
{ path: '*', redirect: '/home' },
],
})
そしてリンク埋め込み
<template>
<v-app id="app">
<v-navigation-drawer v-model="drawer" clipped fixed app >
<v-list dense>
<r-link linkname='home'></r-link>
<r-link linkname='admin_user'></r-link>
<r-link linkname='admin_payslip'></r-link>
★ <r-link linkname='admin_actlog'></r-link>
</v-list>
</v-navigation-drawer>
<v-toolbar color="primary" dark fixed app clipped-left>
~~~~
Laravel 操作ログのコントローラ
クライアント(Vue)からの一覧表示要求に答えるコントローラを追加しときます
ついでにCSV ダウンロード機能も
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Actlog;
use App\Facades\Csv;
class ActlogController extends Controller
{
public function index()
{
Log::Debug(__CLASS__.':'.__FUNCTION__);
$actlog = Actlog::where('user_id', '>', '0')
-> whereNotNull('route')
-> orderby('created_at', 'desc')
-> limit(100)
-> get();
return ['data' => $actlog];
}
public function download(Request $request)
{
Log::Debug(__CLASS__.':'.__FUNCTION__, $request->all());
// 取得項目設定
$head = ['created_at', 'route', 'status', 'remote_addr', 'user_agent', 'user_id'];
// 抽出
$data = Actlog::select( $head )
-> where('user_id', '>', '0')
-> whereNotNull('route')
-> orderby('created_at', 'desc')
-> get()
-> toArray();
// 自動付与の名前をヘッダーに追加
$head[] = 'name';
// CSV DOWNLOAD
return Csv::download($data, $head, 'test.csv');
}
}
ログイン後の操作履歴( user_id > 0 )だけを表示するようにしてます
さらに正規の要求(whereNotNull route)の履歴だけを対象に
ついでに直近100件(limit 100)のみを表示対象としときます
Laravel ルーティング設定
コントローラを追加したのでルーティングも設定
<?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('home');
})->middleware('auth');
// Authentication Routes...
Route::get('/login', 'Auth\LoginController@showLoginForm') -> name('login.show');
Route::post('/login', 'Auth\LoginController@login') -> name('login');
Route::post('/logout', 'Auth\LoginController@logout') -> name('logout');
// Admin
Route::GROUP(['middleware' => ['auth', 'can:admin']], function() {
Route::prefix('/api/admin/') -> name('admin.') -> group(function() {
// USER
Route::name('user.') -> group(function() {
Route::post('user', 'UserController@index') -> name('index');
Route::post('user/store', 'UserController@store') -> name('store');
Route::post('user/destroy', 'UserController@destroy') -> name('destroy');
Route::post('user/download', 'UserController@download') -> name('download');
Route::post('user/upload', 'UserController@upload') -> name('upload');
});
// CsvPayslip
Route::name('csvpayslip.') -> group(function() {
Route::post('csvpayslip/index', 'CsvPayslipController@index') -> name('index');
Route::post('csvpayslip/upload', 'CsvPayslipController@upload') -> name('upload');
Route::post('csvpayslip/delete', 'CsvPayslipController@delete') -> name('delete');
Route::post('csvpayslip/publish', 'CsvPayslipController@publish') -> name('publish');
});
// Payslip
Route::name('payslip.') -> group(function() {
Route::post('payslip/index', 'PayslipController@index') -> name('index');
Route::post('payslip/delete', 'PayslipController@delete') -> name('delete');
Route::post('payslip/pdf', 'PayslipController@pdf') -> name('pdf');
});
★ // Actlog
Route::name('actlog.') -> group(function() {
Route::post('actlog', 'ActlogController@index') -> name('index');
Route::post('actlog/download', 'ActlogController@download') -> name('download');
});
});
});
// Other
Route::get('/{any}', function () {
return view('home');
})->middleware('auth')->where('any', '.*');
一覧画面動作確認
以上
ミドルウェアとして登録したことで処理系には一切手を入れずにアクションログを自動で記録できるようになりました
Laravel ステキ
今回もソースはこちら
https://github.com/u9m31/u9m31/tree/step14