cakePHPでPEAR::Cache_Liteを使う

cakePHPのcachehelperについて、cacheしていてもControllerが動作してしまう...

http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=1075&forum=7

原因が特定出来なかったので、しょうがないからPEAR::Cache_Liteを使用する事にした。

しかし、Cache_Liteはcacheする時に

$cache_lite->save($output);

この様に出力結果をsave()関数に渡さなければいけないのだけれど、cakePHPで出力結果を変数に渡す方法が判らない...

Contorollerで

$this->render();

とすれば出力されるのは判るんだけど、欲しいのは出力される内容なので$this->render();では駄目。

しょうがないのでgetRenderという関数を作った。

libs/controller/controller.php

<?php
function getRender($action = null, $layout = null, $file = null) {
	$viewClass = $this->view;
	if ($this->view != 'View') {
		$viewClass = $this->view . 'View';
		loadView($this->view);
	}
	$this->beforeRender();
	$this->__viewClass =& new $viewClass($this);

	if (!empty($this->modelNames)) {
		$models = array();
		foreach ($this->modelNames as $currentModel) {
			if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model')) {
				$models[] = Inflector::underscore($currentModel);
			}
			if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model') && !empty($this->$currentModel->validationErrors)) {
				$this->__viewClass->validationErrors[Inflector::camelize($currentModel)] =& $this->$currentModel->validationErrors;
			}
		}
		$models = array_diff(ClassRegistry::keys(), $models);
		foreach ($models as $currentModel) {
			if (ClassRegistry::isKeySet($currentModel)) {
				$currentObject =& ClassRegistry::getObject($currentModel);
				if (is_a($currentObject, 'Model') && !empty($currentObject->validationErrors)) {
					$this->__viewClass->validationErrors[Inflector::camelize($currentModel)] =& $currentObject->validationErrors;
				}
			}
		}
	}
	$this->autoRender = false;
	return $this->__viewClass->getRender($action, $layout, $file);
}
?>

libs/view/view.php

<?php
	function getRender($action = null, $layout = null, $file = null) {

		if (isset($this->_hasRendered) && $this->_hasRendered) {
			return true;
		} else {
			$this->_hasRendered = false;
		}

		if (!$action) {
			$action = $this->action;
		}
		$tempLayout = $this->layout;

		if ($layout) {
			$this->setLayout($layout);
		}

		if ($file) {
			$viewFileName = $file;
		} else {
			$viewFileName = $this->_getViewFileName($action);
		}

		if (!is_null($this->plugin) && is_null($file)) {
			return $this->pluginView($action, $layout);
		}

		if (!is_file($viewFileName) && !fileExistsInPath($viewFileName) || $viewFileName === '/' || $viewFileName === '\\') {
			if (strpos($action, 'missingAction') !== false) {
				$errorAction = 'missingAction';
			} else {
				$errorAction = 'missingView';
			}

			foreach (array($this->name, 'errors') as $viewDir) {
				$errorAction = Inflector::underscore($errorAction);

				if (file_exists(VIEWS . $viewDir . DS . $errorAction . $this->ext)) {
					$missingViewFileName = VIEWS . $viewDir . DS . $errorAction . $this->ext;
				} elseif ($missingViewFileName = fileExistsInPath(LIBS . 'view' . DS . 'templates' . DS . $viewDir . DS . $errorAction . '.thtml')) {
				} else {
					$missingViewFileName = false;
				}

				$missingViewExists = is_file($missingViewFileName);

				if ($missingViewExists) {
					break;
				}
			}

			if (strpos($action, 'missingView') === false) {
				return $this->cakeError('missingView', array(array('className' => $this->controller->name,
																					'action' => $action,
																					'file' => $viewFileName,
																					'base' => $this->base)));

				$isFatal = isset($this->isFatal) ? $this->isFatal : false;

				if (!$isFatal) {
					$viewFileName = $missingViewFileName;
				}
			} else {
				$missingViewExists = false;
			}

			if (!$missingViewExists || $isFatal) {
				if (Configure::read() > 0) {
					trigger_error(sprintf("No template file for view %s (expected %s), create it first'", $action, $viewFileName), E_USER_ERROR);
				} else {
					$this->error('404', 'Not found', sprintf("The requested address %s was not found on this server.", '', "missing view \"{$action}\""));
				}
				die();
			}
		}

		if ($viewFileName && !$this->_hasRendered) {
			if (substr($viewFileName, -5) === 'thtml') {
				$out = View::_render($viewFileName, $this->viewVars);
			} else {
				$out = $this->_render($viewFileName, $this->viewVars);
			}

			if ($out !== false) {
				if ($this->layout && $this->autoLayout) {
					$out = $this->renderLayout($out);
					if (isset($this->loaded['cache']) && ((isset($this->controller) && $this->controller->cacheAction != false)) && (defined('CACHE_CHECK') && CACHE_CHECK === true)) {
						$replace = array('<cake:nocache>', '</cake:nocache>');
						$out = str_replace($replace, '', $out);
					}
				}

				#print $out;
				$this->setLayout($tempLayout);
				$this->_hasRendered = true;
			} else {
				$out = $this->_render($viewFileName, $this->viewVars);
				trigger_error(sprintf("Error in view %s, got: <blockquote>%s</blockquote>", $viewFileName, $out), E_USER_ERROR);
			}
			return $out;
		}
	}

?>

これでControllerで

	$cache_lite = new Cache_Lite($cache_options);
	$cache_lite->save($this->getRender());

の様にすれば、Cache_Liteのsave()関数にviewを渡せるので、

cakePHPでCache_Liteを利用してしてcacheする事が出来る。

ニコニコLinkのトップページが今まで12秒かかっていたのがCache_Lite使用後は1秒程度になった。
これでようやく前進できそうだ。
明日からはニコニコ動画への負荷をもうちょっと減らせる修正をしよう。