拡張子を好きなものに変える方法の追い方

CakePHP 1.2.1です

一つ前の記事で、
「ctp以外の拡張子ファイルをviewファイルとして扱う」
http://d.hatena.ne.jp/cakephper/20090205/1233809420
を書きました。

その方法はソースコードを追っていくものだったので、今回はその流れを書いていきます。

まずは、コントローラで

$this->render();

とやってviewファイルをセットしているので、この辺から見ていきます。

まずは、cake/libs/controller/controller.phpを見ていきます。ここで「render(」という文字列で検索をかけると、下記のファンクションがヒットします。重要な行だけ抜粋してます。

	function render($action = null, $layout = null, $file = null) {

		$View =& new $viewClass($this);

		$this->output .= $View->render($action, $layout, $file);

		return $this->output;
	}

Viewクラスにあるrenderメソッドを呼んでいるのが分かります。第一引数の$actionは好きなアクション名を指定できるので、このアクション名に.ctpがどのタイミングで付け加えられるか見ていけばよいかなと思いました。


ということで、次にViewクラスを見ていきます。
cake/libs/view/view.phpのファイルで「render(」という文字列で検索をかけ、該当メソッドに飛びます。
下記の該当箇所で重要なところだけ抜粋しています。

	function render($action = null, $layout = null, $file = null) {

		if ($action !== false && $viewFileName = $this->_getViewFileName($action)) {
			if (substr($viewFileName, -3) === 'ctp' || substr($viewFileName, -5) === 'thtml') {
				$out = View::_render($viewFileName, $this->viewVars);
			} else {
				$out = $this->_render($viewFileName, $this->viewVars);
			}
		}


	}

ここを見ると、_getViewFileNameメソッドでviewファイル名を取得して$viewFileNameに入れて、そのファイル名を使って_renderメソッドでレンダリング処理をしています。


ということで、_getViewFileNameが怪しいので同一ファイル内で「_getViewFileName」で検索してそのメソッドに飛びます。ここも重要な箇所のみ抜粋してます。

	function _getViewFileName($name = null) {
		if ($name === null) {
			$name = $this->action;
		}

		foreach ($paths as $path) {
			if (file_exists($path . $name . $this->ext)) {
				return $path . $name . $this->ext;
			} elseif (file_exists($path . $name . '.ctp')) {
				return $path . $name . '.ctp';
			} elseif (file_exists($path . $name . '.thtml')) {
				return $path . $name . '.thtml';
			}
		}
	}

アクション名が与えられてなければ、$this->actionの値がviewのファイル名となります。
次のforeachでパスを検索して、まず最初に該当パスに該当のアクション名+拡張子($this->ext)のファイルがあるかチェックしてます。ファイルがなければ拡張子ctpを探し、なければ拡張子thtmlを探してます。


ということで、好きな拡張子を$this->extにセットしれやればいいんですね!デフォルトではview.phpの最初の方で

var $ext = '.ctp';

としているのでこれを書き換える方法を探します(直接書き換えるとバージョンアップの時に面倒なので間接的に書き換える方法を模索します。)

「ext」という文字列で検索していくと、下記の箇所が該当します

	var $__passedVars = array(
		'viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot',
		'helpers', 'here', 'layout', 'name', 'pageTitle', 'layoutPath', 'viewPath',
		'params', 'data', 'plugin', 'passedArgs', 'cacheAction'
	);

これを使って何か初期値を与えてそうな感じなので、「$__passedVars」で検索すると、Viewクラスをインスタンス化した際に呼ばれるview.phpのコンストラクタがヒットします。

その箇所を見ると

	function __construct(&$controller, $register = true) {
		if (is_object($controller)) {
			$count = count($this->__passedVars);
			for ($j = 0; $j < $count; $j++) {
				$var = $this->__passedVars[$j];
				$this->{$var} = $controller->{$var};
			}
		}
		parent::__construct();

		if ($register) {
			ClassRegistry::addObject('view', $this);
		}
	}

$this->{$var} = $controller->{$var};この箇所で$this->extの値をコントローラの変数で上書きしています。

ということで、View.php

var $ext = '.ctp';

という初期値の箇所を書き換えるには、コントローラ側で同じように

var $ext = '.html';

とセットしてやれば良いことが分かりました。