RitoLabo

CakePHPの認証機能に最終ログイン日時の記録を追加する(ビヘイビア/イベント)

  • 公開:
  • カテゴリ: PHP CakePHP
  • タグ: PHP,Events,Auth,login,CakePHP,3.5,Behavior

CakePHPの場合、認証コンポーネントを使う事で簡単にログイン機能を構築できますが、最終ログインの記録部分に関してはデフォルトでは機能実装は行われていません。

とはいえ、必要なら各自で構築してね。という手前までのエッセンスは提供されています。具体的には、ビヘイビアとイベントを使う事で簡単にその機能を構築する事ができます。

今回はビヘイビアとイベントを使って、最終ログイン日時の記録を追加します。

アジェンダ
  1. 開発環境
  2. ビヘイビア
  3. ビヘイビアとイベントの定義
  4. コントローラへの追加実装
  5. 動作確認

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • MySQL 5.7
  • PHP 7.2
  • CakePHP 3.5

CakePHPのルートディレクトリを「cakephp/」とします。

尚、今回は認証コンポーネントにてログイン機能を構築している事を前提として進めるので、まだの場合は以下を参考にしてください。
CakePHP3の認証[Auth]コンポーネントを用いてログイン機能を実装する

ビヘイビア

CakePHPでのビヘイビア(Behavior)とは、モデル間の共通処理クラスの事で、ある一つのモデルだけの処理ではなく、複数のどのモデルでも使うような、そういった処理をビヘイビアとして定義し、必要な時に呼び出して使う事の出来るクラスです。

例えば今回はデフォルトで提供されているTimestamp Behaviorを使いますが、このビヘイビアでは、日時、タイムスタンプの発行に関するビヘイビアです。

ビヘイビアとイベントの定義

まずはモデルにビヘイビアとイベントを定義していきます。

cakephp/src/Model/Table/UsersTable.php
public function initialize(array $config)
{
// 追加
$this->addBehavior('Timestamp', [
'events' => [
'Users.login' => [
'last_login_at' => 'always'
],
]
])
;
}

デフォルトでTimestampビヘイビアがロードされているので、それにイベントを追加しています。上記の場合、ログインイベントが発火した際には常にlast_login_atカラムに対して、タイムスタンプを発行するという流れになっています。(追加部分のみの記述です)

コントローラへの追加実装

LoginControllerへ最終ログインを記録する為の追加記述を行います。

cakephp/src/Controller/LoginController.php
<?php
namespace App\Controller;

use App\Controller\AppController;

/**
* Login Controller
*
*
* @method \App\Model\Entity\Login[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class LoginController extends AppController
{
/**
* ログイン
*
* @return \Cake\Http\Response|void
*/
public function index()
{
$this->viewBuilder()->layout(false);

if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);

// 最終ログイン日時を記録する
$this->loadModel('Users');
$user_entity = $this->Users->get($user['id']);
$user_entity->dirty('modified', true);
$this->Users->touch($user_entity, 'Users.login');
$this->Users->save($user_entity);

return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('ユーザ名もしくはパスワードが間違っています'));
}
}

/**
* ログアウト
* @return \Cake\Http\Response|null
*/
public function logout()
{
return $this->redirect($this->Auth->logout());
}

}

上から説明すると、以下のような処理手順になっています。

Usersモデルを読み込みます。

// Usersモデルの読み込み
$this->loadModel('Users');

ログインユーザのエンティティを取得します。

// ログインユーザのエンティティを取得
$user_entity = $this->Users->get($user['id']);

保存時に更新日は更新しない設定を行います。ここは必要なければ記述しなくても問題ありません。

// 更新日は更新しない
$user_entity->dirty('modified', true);

イベントを発火させます。ビヘイビアで定義したあれです。

// イベント発火
$this->Users->touch($user_entity, 'Users.login');

そして最後に、ユーザデータの保存を行います。

// ユーザデータの保存
$this->Users->save($user_entity);

動作確認

設定が完了したので、実際にログインを行い確認してみます。

# ログイン前
mysql> select id, username last_login_at, modified from users;
+----+---------------+---------------------+---------------------+
| id | username | last_login_at | modified |
+----+---------------+---------------------+---------------------+
| 1 | user01 | 2018-04-15 23:09:35 | 2018-04-15 23:09:35 |
+----+---------------+---------------------+---------------------+

# ログイン後
mysql> select id, username last_login_at, modified from users;
+----+---------------+---------------------+---------------------+
| id | username | last_login_at | modified |
+----+---------------+---------------------+---------------------+
| 1 | user01 | 2018-04-16 22:36:02 | 2018-04-15 23:09:35 |
+----+---------------+---------------------+---------------------+

ログイン後に最終ログインカラムが更新されている事が確認できました。

まとめ

作業は以上で完了です。今回のように構築してしまえば、日時の取り回しなど一切気にしなくてよくなるので効率的ですし、ソースコードも簡素化出来てとても良いので是非試してみてください。