エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP 2.3 ログイン、操作履歴、アクセスログ出力

      2017/03/11

CakePHP 2.3系でログイン履歴、操作履歴、アクセスログなどのログ出力方法

 

ログ出力を作ることになった経緯

 
今回は、ログイン履歴、操作履歴、アクセスログといったログの出力に関しての説明です。
 
操作ログの出力に関しては、簡単に出力できるだろうと考えていたのですが、実は意外に実装が難しかったですね。(実はそれほど難しいものじゃないのですが、CakePHPの仕様を分かっていなくてさんざん悩んでしまった、というだけですが...)
 
最初はもしかすると、操作ログのプラグインがあるんじゃないか、とさえ思ったのですが、そこまで甘くはなかったわけです。
単純なすべてのアクセスのログを取るものや、SQLのログを取るものはありましたが、当然ながらオリジナルで作成している Webシステムに合わせて柔軟なログを出力したい、なんていう要望が叶えられるようなものはなかったワケです。
 
 

ログ出力をファイルに出力する方法

 
今回は、まず下記のサイトを参考に Vendor内に Classを作り、処理を構築しました。
http://neoinspire.net/archives/34#.UfXaItaChph
 
ちなみに、Vendorに設置した classの呼び出し方法は、CakePHP2.Xでは変更になっていますので、下記のサイトを参考にしました。
http://www.monoreview.com/?p=35
 
————–(/app/Vendor/accesslogs.php)

<?php
class AccessLogs{
  function write_log() {
    $msg = date('Y-m-d H:i:s') . "," . env('REQUEST_URI') . "," . env('HTTP_REFERER') . "," . env('HTTP_USER_AGENT') . "," . env('REMOTE_ADDR') . "\n";

    $filename = LOGS . 'accesslogs/' . date('Ymd') . '.log';
    $log = new File($filename);
    $log->append($msg);

    return true;
  }
}
?>

————–
 
————–(/app/AppController.php)

<?php
App::import('Vendor', 'accesslogs');

class AppController extends Controller {
  public function beforeFilter() {
    $this->access = new AccessLogs();
    $this->access->write_log();
  }
}

————–
 
続けて、「cake/app/tmp/logs/」の中に「accesslogs」というフォルダを作ってください。
Linux系のサーバであれば、書き込み権限を設定してください。
 
これで、上記に作成したフォルダの中にログが出力されるようになります。
 
非常に簡単にアクセスログを出力する処理が作れましたので、これは今後の勉強になったかと思っています。
ですが、これをいざ実際に必要としているログイン履歴や、各ページでの操作ログを DBに保存させる処理に拡張しよう、としたら途端に分からなくなったのです。
 
 


 

ログ出力データベースに保存する方法

 
そんなわけで、寄り道も含めて、全く違う方法で DBにログを保存する方法を探したところ、参考になりそうな下記のサイトが見つかりました。
http://pc.casey.jp/archives/750
 
こちらを参考にしながら、テーブル名は、Historyに変更し、認証処理など不要な項目を削除しました。
 
————–(テーブル)

CREATE TABLE IF NOT EXISTS `histories` (
  `id`       int(10)   unsigned NOT NULL AUTO_INCREMENT,
  `created`  timestamp          NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `system`   varchar(64)        NOT NULL,
  `level`    varchar(6)         NOT NULL,
  `client`   varchar(15)        NOT NULL,
  `message`  varchar(512)       NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

————–
 
————–(/app/HistoriesController.php)

<?php
class HistoriesController extends AppController {
  var $name = 'Histories';

  function beforeFilter(){
    parent::beforeFilter();
  }

  function admin_index() {
    $this->write_log(__METHOD__, 'info', 'Display list view.');
    $this->set('histories', $this->paginate('History'));
  }
}
?>

————–
 
「class AppController extends Controller」の中に「write_log」の関数を編集します。
 
————–(/app/AppController.php)

class AppController extends Controller {
  function write_log($systemName, $level, $message){
    $ip = 2;
    $data = array(
      'system' => $systemName,
      'level'  => $level,
      'message' => $message,
      'client' => $ip,
      'created' => '',
    );
    $this->History->create();
    $this->History->save($data);
  }
}

————–
 
————–(/View/Histories/admin_index.ctp)

<?php
?>
<h1>システム稼動ログ一覧</h1>
<table>
 <tr>
  <th>日時</th>
  <th>システム</th>
  <th>レベル</th>
  <th>クライアント</th>
  <th>内容</th>
 </tr>
 <!-- $remotes配列をループして、投稿記事の情報を表示 -->
 <?php foreach ($histories as $history): ?>
 <tr>
  <td><?php echo $history['History']['created']; ?></td>
  <td><?php echo $history['History']['system'];?></td>
  <td><?php echo $history['History']['level'];?></td>
  <td><?php echo $history['History']['client'];?></td>
  <td><?php echo $history['History']['message'];?></td>
 </tr>
 <?php endforeach; ?>
</table>

————–
 
上記までの設定をすることで、ログ出力ができると思います。
一覧ページでリロードするたびにログのレコードが増えていくことが分かるでしょう。
 
 
これはこれで問題ないのですが、操作ログとして処理を作成する場合は、History以外のページでもログを出力する必要が出てきますので、その対応を作ってみました。
例えば、ログイン時にログインのログを出力する場合は、Usersでログを出力させる必要があると思いますので、まず「/Model/User.php」に Historyとの belongsToの設定を行います。
 
————–(/Model/User.php)

    :
    :
  public $belongsTo = array (
    'History' => array(
      'className' => 'History',
      'foreignKey' => 'id',
      'conditions' => '',
      'fields' => '',
      'order' => ''
    ),
  );
    :
    :

————–
 
続いて、「/app/HistoriesController.php」には、どのコントローラーからのアクセスなのかの情報を引数として設定します。
 
————–(/app/HistoriesController.php)

<?php
class HistoriesController extends AppController {
  var $name = 'Histories';

  function beforeFilter(){
    parent::beforeFilter();
  }

  function admin_index() {
    $ctr_name = $this->name;
    $this->write_log(__METHOD__, 'info', 'Display list view.', $ctr_name);
    $this->set('histories', $this->paginate('History'));
  }
}
?>

————–
 
さらに、「/app/AppController.php」でデータを保存する処理では、Userテーブルとの連携の設定を行います。(「HistoriesController.php」から送られてくるコントローラー名をもとに、テーブルの連携処理を振り分けます。)
これで、History以外のページからも Historyテーブルへログ保存の処理が行えるようになります。
 
————–(/app/AppController.php)

class AppController extends Controller {
  function write_log($systemName, $level, $message, $ctr_name){
    $ip = 2;
    $data = array(
      'system' => $systemName,
      'level'  => $level,
      'message' => $message,
      'client' => $ip,
      'created' => '',
    );
    if ( $ctr_name == 'Histories' ) {
      $this->History->create();
      $this->History->save($data);
    } else {
      $this->User-> History->create();
      $this->User-> History->save($data);
    }
  }
}

————–
 
この処理は、ログを出力するコントローラの数が増えれば増えるほど分岐が増えますので、もう少しいい書き方を検討する必要があるとは思いますが。
 
 
また、ログインの処理については、よくあるログイン処理をそのまま記述していると、「autoRedirect」が有効になっているため、ログイン認証が有効になったとたんに「loginRedirect」で設定してあるページに遷移してしまいます。
そのため、リダイレクトをさせる前にログ出力の処理を入れるためには、「autoRedirect」を無効にする必要がありますが、その設定に関しては、下記のサイトに分かりやすく説明がありました。
http://hima-j.in/cakephp/cakephp-last-login/
 
 

参考になるサイト

 
最後に、この記事を書くに当たって参考にしたサイトと自分でも書いてみた記事を紹介しておきます。
 
DBに値を保存する「save」メソッドに関しては下記の 2サイトが分かりやすく説明してありましたので、とても勉強になりました。
http://www.garacter.com/notes/cakephp/model/save
http://www.kaasan.info/archives/2543
 
また、下記の記事も書いていますのでご覧ください。
 CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll
 CakePHP 2.3で saveの便利な使い方・サンプルソース付き

 - CakePHP 3.x 4.x 5.x

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP 2.3 Search Pluginで検索処理 その1設置方法

CakePHPの検索プラグイン Search Pluginの設置方法と基本的な検索処理の解説です。

CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説

CakePHP3でOGPを設定する方法を解説。fetch、assignを使用しレイアウトファイルに編集した変数にテンプレートファイルから値を指定する。これを利用してOGPを編集する。

CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説

CakeDC謹製Usersプラグインの紹介。Usersのカスタマイズとして入力項目のバリデーションの変更を、プラグインのファイルは触らずオーバーライドにより実装する方法を解説する。

CakePHP3で画像・ファイルのアップロード処理を自作・解説付き・その2
CakePHP3で画像・ファイルのアップロード処理を自作・解説付き・その2

ファイルのアップロード機能の自作サンプルコードとその解説のその2。アップロード機能に関連するファイルの更新や削除の処理や画像、フォルダのパスの指定方法などを含めて解説。

CakePHP 2.3でOn Duplicate Key構文を実装

CakePHPで On Duplicate Key構文を Queryを利用して実装する方法をサンプルソース付きで解説します。

CakePHP3でページごとに読み込むJavaScript、CSSを変える処理の解説
CakePHP3でページごとに読み込むJavaScript、CSSを変える処理の解説

CakePHP3でJavaScriptやCSSを編集する基本形から、それらやテンプレート(エレメント)を特定のテンプレートを読み込んだときのみ編集、実行するための方法、ブロック化について解説。

CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合
CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合

CakePHP3で開発環境と本番環境とで違う設定ファイルを読み込ませて環境ごとに定数を切り替える方法を解説。Apacheのhttpd.confに環境変数を設定し、それを読み込み判別する。

CakePHP3のHtmlHelperのLink設定のまとめ。mailto、URL、Root/Homeのリンクなども
CakePHP3のHtmlHelperのLink設定のまとめ。mailto、URL、Root/Homeのリンクなども

CakePHP3でHtmlHelperを使ってリンクの設定をする方法のまとめ。基本形からURLを指定、class、id、targetを指定、mailtoのリンク、画像をアンカーに、JavaScriptのダイアログなどの解説。

CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法

CakePHPの検索プラグイン Search Pluginの検索処理の中で入力エリア一つで複数の項目を同時に検索する方法を解説。

CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も

CakePHP3で Insert … On Duplicate Key Update構文(upsert)を実行する方法を解説。バルク処理の方法も用意されているため大量処理の場合も対応可能。


Warning: Trying to access array offset on null in /home/ss-giken/s-giken.net/public_html/blog/wp-content/plugins/amazonjs/amazonjs.php on line 637