EthnaのURLを綺麗にする(Ethna_UrlHandlerを使う方法)

やっぱりEthnaのURLって微妙だよね?
てなことで、前々から興味があったけれどやっていなかったのを調べてみました。

似た話題

http://rd.uniba.jp/blog/2010/06/30/ethna-%E3%81%A7%E7%B6%BA%E9%BA%97%E3%81%AA-url-ethna_urlhandler-%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E6%96%B9%E6%B3%95/
Ethna で綺麗な URL (Ethna_UrlHandler を使わない方法)

ここが最初に検索するとひっかかります。
うん、いまちゃんと読んだけれどこっちの方が楽です(笑)

でも。。。

example.org/hogehoge/fugagufa/?id=10

こうじゃなくって

example.org/hogehoge/fugagufa/10

こうしたいときってありますよね?
まあ、私はあまりないのですが(汗)

方針

Ethna_UrlHandlerがあるので、Ethna_UrlHandlerを拡張して再現したいと思います。ただし、Ethna_UrlHandlerは事前にすべてのアクションを登録しておく必要があるので、非常に面倒です。。。

流れ的にはアクセスしてきたURLをみて、動的にアクションとの紐付けを設定してあげます。

コード(pjname\app\Pjname_Testethna_UrlHandler.php)

<?php
  function &getInstance($class_name = null)
  {
    $instance =& parent::getInstance(__CLASS__);

    // add
    $path = parent::_normalizePath($_SERVER['PATH_INFO']);
    $acrion_list = split( "/", $path[0] );

    $ctl = &Ethna_Controller::getInstance();

    while( count($acrion_list) ){
      $action_name = implode( "_", $acrion_list );

      if( $ctl->getActionClassName($action_name) ){
        break;
      }

      array_pop($acrion_list);
    }
    $url_path = implode( "/", $acrion_list );

    $instance->action_map = array(
      $_SERVER['URL_HANDLER'] => array(
        $action_name => array(
          'path'     => $url_path,
          'path_regexp'  => '|^'.$url_path.'/(.*)$|',
          'path_ext'   => array('url_param' => array()),
        ),
      ),
    );
    // add-end

    return $instance;
  }

上記の部分に無理やり突っ込んでいます。内容はPATH_INFOを取ってきて、整形後にgetActionClassName()を利用して、実在するAction名を探して、それ以降の/はパラメータとしています。

準備

http://ethna.jp/ethna-document-dev_guide-urlhandler.html
ここを参考にして、事前準備が必要です。

$action_map の設定

ここは動的に作っているので必要ありません

_getPath_Index() 関数の定義

ここは動的に作成できないので、{url}を使うことができません。なので設定の必要はありません。

URL_HANDLER 変数の設定

これは必要です。

$config['url'] の設定

なくても動きますが、設定したほうがよいかもしれません。(未検証)

echo_msgアクションを追加

対象アクションは必要です。

値の受け取り方とアクセスURL

example.org/index.php?action_echo_msg=true

通常のURLが上記の場合

example.org/index.php/echo/msg

でアクセスができるようになります。サーバーによっては拡張子を除くことができるので

example.org/index/echo/msg

でも可能です。index.phpの名前を変更することでもっと短い名前にもできますし、mod_rewriteを利用して無くすことも可能ですね。

パラメーターの受け取り方

<?php
    var $form = array(
        'url_param' => array(),
    );

上記のように設定することで index.php/echo/msg/123/456/789 のアクセスの場合 123/456/789 が取り出せます。このままだと使いにくいので

<?php
    var $form = array(
        'num' => array(
            'type'        => VAR_TYPE_INT,
	    'form_type' => FORM_TYPE_TEXT
	),

        'url_param' => array(),
    );

上記のように分解して入れる変数を用意し

<?php
    function prepare()
    {
        $_url_param = split( "/", $this->af->get('url_param' ) );
        $this->af->set('num', $_url_param[0] );

        var_dump($this->af->validate());

        return null;
    }

上記のように分解してから、パラメータを代入してvalidateをかけることで安全に利用することができます。もしくは index.php/echo/msg/0/?num2=1244 とかでもデータは取れます。

総括

本当はパラメータのどこが、どこに対応するのかをまでafの設定の中にいれることで、パラメータの代入まで自動化できると思います。

<?php
    var $form = array(
        'num' => array(
	    'type'        => VAR_TYPE_INT,
	    'form_type' => FORM_TYPE_TEXT,
	    'url_param_num' => 0
        ),
    );

上記みたいに紐付けて、url_param_numがついているパラメータを自動代入がきれいかな。。。

まあ、アクション名をecho_msgみたいな形で妥協すればもっと簡単になるんですが、そこはきれいじゃないですよね?