CodeIgniter: hookを使ってbefore_filterやってみる。

CodeIgniterでコントローラーでbefore_filterやafter_filterするにはどうすればいいんだろう?と思い、調べてみたところ、CodeIgniterではフックが使えるらしいです。

フックとは、決められたタイミングで行われるコールバックのことです。
今回は認証機能をフックで呼んでみるような感じのサンプルを作ってみます。

  1. application/config/config.phpの$config[‘enable_hooks’]をTRUEに設定します。
  2. application/config/hooks.phpに、フックで使用するクラスを指定します。ここでは、BeforeFilterクラスを指定してみます。
    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    // コントローラーのコンストラクタが終了したタイミングで呼ばれるフック名
    $hook['post_controller_constructor'] = array(
      'class'     => 'BeforeFilter', // 呼ぶクラス名
      'function'  => 'is_login', // 呼ぶメソッド
      'filename'  => 'before_filter.php', // ファイル名
      'filepath'  => 'hooks' // applicationフォルダからの相対パス
    );
    

    フックのタイミングは色々あります。一覧を記述します。

    pre_system
    システム実行の最初に呼ばれる。ベンチマーククラスとフッククラスだけロードされている。ルーティングはまだ。
    pre_controller
    コントローラーが呼ばれる直前に呼ばれる。すべての基本クラスのロード、ルーティング、セキュリティチェックなどが終わっている
    post_controller_constructor
    コントローラーがインスタンスされた直後。Railsのbefore_filterのタイミング。
    post_controller
    コントローラーが完全に実行された直後。Railsのafter_filterのタイミング。
    display_override
    ブラウザに送信するdisplayメソッドをオーバーライドした動きになる。処理済みのデータは$this->output->get_output()で取得可能。
    cache_override
    display_cacheメソッドの代わりに独自のメソッドを呼び出すことが可能なタイミング。独自キャッシュメカニズムとかに使える。
    post_system
    ブラウザに送信し終わったときのタイミング。ベンチマークをとるようなところ。

    今回はbefore_filterのようなフックを作りたかったので、post_controller_constructorを指定しています。また、同じタイミングで複数のフックを仕掛けたい場合は、二次元配列にすることで指定できます。次のようにするとよいでしょう。

    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    // コントローラーのコンストラクタが終了したタイミングで呼ばれるフック名
    $hook['post_controller_constructor'][] = array(
      'class'     => 'Hoge',
      'function'  => 'foo',
      'filename'  => 'hoge.php',
      'filepath'  => 'hooks'
    );
    $hook['post_controller_constructor'][] = array(
      'class'     => 'Fuga',
      'function'  => 'bar',
      'filename'  => 'fuga.php',
      'filepath'  => 'hooks'
    );
    
  3. さて、あとはフックで呼ばれる対象のクラスを作成するだけです。application/hooks/before_filter.phpを作成します。
  4. before_filter.phpを以下のように記述します。
    <?php
    class BeforeFilter {
      private $CI;
    
      public function __construct() {
        // CIオブジェクトを取得
        $this->CI =& get_instance();
      }
    
      function is_login() {
        if(!$this->CI->session->userdata('logged_in') &&
           $this->CI->uri->uri_string != '/auth/login') {
          // ログインしていない
          redirect('auth/login');
        }
      }
    }
    

    CIオブジェクトをget_instance()で取得してしまえば、あとはどうとでもなると思います。ここでは、セッションにログイン情報が入っているかを見てます。ただし、ログイン画面でもチェックしてしまうと無限ループになるので、ログイン画面以外でのチェックにしています。

Rails風なものと違って、別ファイルでフィルタ(フック)を定義するのですが、まぁ使い方はほとんど同じだなーという感じです。とりあえずこれでログインチェックをいちいち全てで行わなくて済むようになったので一安心です。


タグ CodeIgniter, PHP | パーマリンク.

コメントを残す

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