CodeIgniterの学習 51 - HMVCモジュールの動作確認をしてみる( HMVCを使ってブログパーツチックにコントローラやビュー内で別コントローラ(とそのビュー)を呼べるようにするその3)

今日は昨日の続き。HMVCモジュールの動作確認をしてみる。

モジュール単体でも、CodeIgniter標準のコントーローラと同様に動作するのだが、
このサンプルでは、親のコントローラから呼び出される別コントローラのイメージ
ブログパーツみたいなイメージ)の作り方で動作確認してみる。


CodeIgniterのソース構造(抜粋)

こんな感じでmodulesディレクトリを新設しファイルを作ってみる。
なお親のコントローラ(ビュー)から、子のコントローラ(ビュー)を呼び出すイメージ

(tree抜粋)

application
    |-- controllers
    |   `-- tasklist.php (1:過去に作成済み:親の呼出元コントローラ)
    |`-- views
    |   `tasklist_edit.php (2:過去に作成済み:親の呼出元ビュー,tasklist/edit/が呼ばれたときのビュー)
    |-- libraries
    |   `-- Oreore.php (3:過去に作成済み:動作確認用ライブラリ)
    `-- modules
        `-- mdl_moemoe(モジュール名)
            |-- controllers
            |   `-- mdl_moemoe.php (4:新設:子のモジュール側コントローラ)
            |-- libraries
            |   `-- Moemoe.php (5:新設:子のモジュール内専用ライブラリ)
            |-- models
            |   `-- Moemoe_model.php (6:新設:子のモジュール内専用モデル)
            `-- views
                `-- moemoe_index.php (7:新設:子のモジュール側ビュー)

modules以下が新設。
モジュール名のディレクトリ名と、4のソースの名前をあわせておく。あとは名前はなんでも良い。

モジュール名の頭にmdl_とつけたのは、mdl_から始まるモジュールは直接呼び出しされないようにしたから。(後述)


動作確認ソース

以前のエントリで作りかけたtasklist系のソースにモジュールの呼びだしを埋め込んでみた。(要点のみ抜粋)

(数字は上のtreeと連動)
1:application/controllers/tasklist.php

フォームのサブミット後に4:のメソッドを呼び出してみる箇所の抜粋

<?php
 //上略
  // サブミット時の処理(別に名前はsubmitじゃなくても、formのポスト側と合っていればなんでもいい。)
  function submit()
  {

    //モジュール内コントローラのメソッド呼びだしの例
    var_dump($this->input->post('hmvctest'));
    if( modules::load('mdl_moemoe')->_validate($this->input->post('hmvctest')) ){
      echo '1の呼び方で、TRUE が戻ってきた<hr>';
    }else{
      echo '1の呼び方で、FALSE が戻ってきた<hr>';
    }

    if( $this->load->module('mdl_moemoe')->_validate($this->input->post('hmvctest')) ){
      echo '2の呼び方で、TRUE が戻ってきた<hr>';
    }else{
      echo '2の呼び方で、FALSE が戻ってきた<hr>';
    }

    $objhoge = $this->load->module('mdl_moemoe');

    if( $objhoge->_validate($this->input->post('hmvctest')) ){
      echo '3の呼び方で、TRUE が戻ってきた<hr>';
    }else{
      echo '3の呼び方で、FALSE が戻ってきた<hr>';
    }
    exit;
 }
 //下略
?>

どの呼び方でもモジュール側のコントローラのメソッドを呼び出せる



2:application/views/tasklist_edit.php
tasklist/edit/用のビュー (CodeIgniterは命名規則が緩いので、ビューの名前はなんでも良いが。)

modules::run('モジュール名')

を使うとモジュール側のデフォルトインデックスが内部的に呼び出され結果が差し込まれる。(viewの結果もしくはechoの内容)
(iframeみたいにリクエストが複数回走るわけではない。)


(一部抜粋)

(上略)
<label>郵便番号</label>
<input type="text" name="zipcode" id="zipcode" value="<?=$this->validation->zipcode;?>" size="10" />
<p id="zipcode_error"><?=$this->validation->zipcode_error; ?></p>


<label>HMVCモジュールの実験 mdl_moemoeコントローラを呼び出す<em>*</em></label>
<?= modules::run('mdl_moemoe') ?>
<input type="text" name="hmvctest" id="hmvctest" value="" size="10" />
<p id="hmvctest_error"><?=$this->validation->hmvctest; ?></p>
(下略)



3:application/libraries/Oreore.php
以前のエントリーで作成した、実用性皆無のライブラリ
(モジュール側で共通のライブラリが呼び出せるかどうかの実験用)

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
//俺俺ライブラリのテスト
class Oreore {

    function Oreore(){
    }

    //オープンハート
    function OpenHeart($str="")
    {
        $ret = <<<___END___
<pre class="aa_openheart">
 ヽ('A`)ノ {$str}
  (  )
  ノω|
</pre>
___END___;
        return $ret;
    }

    //タイーホ
    function Taiiho($str="")
    {
        $ret = <<<___END___
<pre class="aa_taiiho">
 __[警]
  (  ) ('A`) {$str}
  (  )Vノ )
   | |  | |
</pre>
___END___;

        return $ret;
    }
    //連続生成
    function OpenTaiiho($num=1,$str1="",$str2=""){
        $ret = "";
        for($i=0;$i<$num;$i++){
            $ret .= self :: OpenHeart($str1);
            $ret .= self :: Taiiho($str2);
        }
        return $ret ;
    }

} //endofclass

 /* End of file Oreore.php */
 /* Location: ./application/libraries/Oreore.php */
?>



4:application/modules/mdl_moemoe/controllers/mdl_moemoe.php
モジュール側コントローラ

こんな感じ。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * モジュール化テスト
 */
// MY_Router.phpを拡張したので、http://example.com/mdl_ から始まるURLにはアクセスできない。それ以外のモジュールにはアクセス出来る

class Mdl_moemoe extends Controller {
  // コンストラクタ
  function Mdl_moemoe()
  {
    parent :: Controller();
  }
  //モジュール内コントローラのデフォルトインデックス
  function index()
  {
    // 共通のライブラリ application/libraries/Oreore.phpをロードしてみる
    $this -> load -> library( 'Oreore' );
    // モジュール内専用のライブラリ application/modules/mdl_moemoe/libraries/Moemoe.phpをロードしてみる
    $this -> load -> library( 'Moemoe' );

    // モジュール内専用のモデルを呼んでみる
    $this -> load -> model( 'Moemoe_model' );

    // モジュール内用のビューを作ってみる
    $data['title'] = 'HMVCを使ってブロブパーツチックに差し込みを行う実験';

    //fugafuga に moemoe_modelモデル の結果と、oreoreライブラリの結果と、moemoeライブラリの結果を格納してみる
    $data['fugafuga'] = $this -> Moemoe_model -> getNanika()  .
                        $this -> oreore -> OpenHeart( 'オープンハート' ) .
                        $this -> moemoe -> OpenHeart() .
                        $this -> oreore -> Taiiho( 'ヤリスギタヨ' );

    //モジュール内のビューを生成
    $this -> load -> view( 'moemoe_index', $data );
  }

  //モジュール内コントローラのメソッドを呼び出すときは
  //方法1: modules::load('mdl_moemoe')->_validate($this->input->post('hmvctest'))
  //方法2: $this->load->module('mdl_moemoe')->_validate($this->input->post('hmvctest'))
  //方法3: $objhoge = $this->load->module('mdl_moemoe');
  //       $objhoge->_validate($this->input->post('hmvctest'));
  //のいずれかの方法で呼べる
  function _validate( $in )
  {
    if( '開けゴマ' === $in ){
      return true;
    }else{
      return false;
    }
  }
}

/**
 * End of file mdl_moemoe.php
 */
/**
 * Location: ./application/modules/mdl_moemoe/controllers/mdl_moemoe.php
 */
 ?>



5:application/modules/mdl_moemoe/libraries/Moemoe.php
モジュール内専用ライブラリのテスト用

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
//モジュール内専用ライブラリのテスト
class Moemoe {

    function Moemoe(){
    }

    //オープンハート
    function OpenHeart($str="")
    {
        $ret = <<<___END___
<pre class="aa_openheart">
 ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ
  (ネ )    (ガ )    (テ )    (ィ )    (ブ )
  ノω|     ノω|     ノω|     ノω|     ノω|
    ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ
     (ハ )    (ー )    (ト )    (に )
     ノω|     ノω|     ノω|     ノω|
 ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ   ヽ('A`)ノ
  (ロ )    (ッ )    (ク )    (オ )    (ン )
  ノω|     ノω|     ノω|     ノω|     ノω|
</pre>
___END___;
        return $ret;
    }

} //endofclass

/* End of file Moemoe.php */
/* Location: ./application/modules/mdl_moemoe/libraries/Moemoe.php */
?>



6:application/modules/mdl_moemoe/models/Moemode_model.php
モジュール内専用モデル 動作確認用に現在時刻を返しているのみ。

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
//モジュール内専用モデルのテスト
class Moemoe_model extends Model {
  function Moemoe_model()
  {
    parent :: Model();
  }
  function getNanika(){
    return date( 'Y-m-d H:i:s', time() );
  }
}
/**
 * End of file Moemode_model.php
 */
/**
 * Location: ./application/modules/mdl_moemoe/models/Moemode_model.php
 */
 ?>



7:application/modules/mdl_moemoe/views/moemoe_index.php
モジュール側のビュー

<div style='background:#00ff00;'>
<span style='color:#ff0000;background:#fff;font-weight:bold;'>
この緑色内ビューは application/modules/mdl_moemoe/views/moemoe_index.php
</span>
<h3><?=$title?></h3>

<?=$fugafuga?><br>

</div>


画面

ブラウザで、http://ホスト名/tasklist/edit/を呼び出すとこんな感じに見える。

ちゃんと動作しているみたいだ。
共通のライブラリも、モジュール内専用のライブラリ・モデル・ビューも読み込めている。




サブミット後の動作はこんな感じ


モジュール側メソッドもちゃんと呼び出せている。



ブラウザで直接モジュールを呼んでみる

ブラウザで、http://ホスト名/mdl_moemoe/ を直接呼んでみる事にする

うむ、ばっちり呼び出せてしまう。
だがしかし、今回のモジュールは直接呼び出して欲しくないのだ。



ルーティングを何とかして、直接呼び出せないようにしてみる。

というわけで、俺仕様で、昨日インストールしたHMVC(modular_extensions_5140)のソースの
application/libraries/MY_Router.php (HMVC 5140)
を俺俺改造してみた。

MY_Router::_validate_request()を多少変更し、
モジュールの頭がmdl_から始まる場合はルーティングから除外する。
(厳密には コントローラ名がmdl_から始まるURLは呼び出せなくする。)

application/libraries/MY_Router.php

<?php
 //上略
  public function _validate_request($segments)
  {
    // /mdl_ から始まるURLはルーティングの対象外とするようにした(URLで直接呼べないように)
    if(isset($segments[0]) && preg_match('#^mdl_#iu',$segments[0])){
      show_404($this->fetch_directory().$segments[0]);
    }else{
    //end
      (isset($segments[1])) OR $segments[1] = NULL;

      /* locate the module controller */
      list($module, $controller) = Router::locate($segments);

      /* no controller found */
      ($module === FALSE) AND show_404($controller);

      /* set the module directory */
      Router::$path = ($controller) ? $module : NULL ;

      /* set the module path */
      $path = ($controller) ? MODOFFSET.$module.'/controllers/' : NULL;

      $this->set_directory($path);

      /* remove the directory segment */
      if ($controller != $module AND $controller != NULL)
        $segments = array_slice($segments, 1);

      return $segments;
    // /mdl_ から始まるURLはルーティングの対象外とするようにした(URLで直接呼べないように)
    }
    //end
  }
 //下略
?>

変更点は、日本語のコメントで挟み込んだ部分

もう一度 http://ホスト名/mdl_moemoe/ を直接呼んでみる事にする

これでmdl_は直接は呼べなくなった。



今日はここまで。



(08/12/15変更)
明日からはこれまでの学習で足りていない(後回しにしていた)、

  • Formヘルパ系の使い方とか挙動とか
  • Version1.7から改良されているform系の使い方
  • Version1.7からのバリデーションの変更点等

ビュー周りの書き方を中心に順次学習する。
書く時間がないので、一旦保留。