cakephpのエレメントをDB管理下に置く

警告

  • このままだれでもアクセスする場所に設置したりすると、外部からどんなphpコードでも実行できてしまいます!
  • この文書は書きかけです
  • これは実験中です!

意見や感想くださいませ

  • 元の処理を踏襲しているつもりですがキャッシュ絡みでおかしな動作したりするかも

テーブルの準備

--
-- テーブルの構造 `elements`
--

CREATE TABLE `elements` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `data` text NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

--
-- テーブルのデータをダンプしています `elements`
--

INSERT INTO `elements` VALUES(1, 'login', '<h2>これはloginエレメントです</h2>', '2011-01-01 00:00:00', '2011-07-14 14:28:27');
INSERT INTO `elements` VALUES(3, 'time', '<?php echo date("H:i:s"); ?>', '2011-07-14 11:12:36', '2011-07-14 11:12:36');

app/views/dbelement.phpを置く

  • view.phpのelementメソッドをオーバーライド
  • _renderメソッドを元に_element_renderとして改造
  • 修正箇所はごく一部
<?php
class DbelementView extends View{
	
	
	
	function element($name, $params = array(), $loadHelpers = false) {
		$file = $plugin = $key = null;

		if (isset($params['plugin'])) {
			$plugin = $params['plugin'];
		}

		if (isset($this->plugin) && !$plugin) {
			$plugin = $this->plugin;
		}

		if (isset($params['cache'])) {
			$expires = '+1 day';

			if (is_array($params['cache'])) {
				$expires = $params['cache']['time'];
				$key = Inflector::slug($params['cache']['key']);
			} elseif ($params['cache'] !== true) {
				$expires = $params['cache'];
				$key = implode('_', array_keys($params));
			}

			if ($expires) {
				$cacheFile = 'element_' . $key . '_' . $plugin . Inflector::slug($name);
				$cache = cache('views' . DS . $cacheFile, null, $expires);

				if (is_string($cache)) {
					return $cache;
				}
			}
		}
		
		
		$this->_element = ClassRegistry::init('Element');
		$element = $this->_element->findByName($name);
		//ターゲットはあるか?
		if($element){
			//あれば_element_render()結果を返す
			$params = array_merge_recursive($params, $this->loaded);
			$element = $this->_element_render($name, array_merge($this->viewVars, $params), $loadHelpers);
			if (isset($params['cache']) && isset($cacheFile) && isset($expires)) {
				cache('views' . DS . $cacheFile, $element, $expires);
			}
			return $element;
			
			
		}else{
			//なければエラーを文字で返す
			return "Element Not Found: " . $name;
		}
		
	}
	
	function _element_render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) {
		$loadedHelpers = array();

		if ($this->helpers != false && $loadHelpers === true) {
			$loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);
			$helpers = array_keys($loadedHelpers);
			$helperNames = array_map(array('Inflector', 'variable'), $helpers);

			for ($i = count($helpers) - 1; $i >= 0; $i--) {
				$name = $helperNames[$i];
				$helper =& $loadedHelpers[$helpers[$i]];

				if (!isset($___dataForView[$name])) {
					${$name} =& $helper;
				}
				$this->loaded[$helperNames[$i]] =& $helper;
				$this->{$helpers[$i]} =& $helper;
			}
			$this->_triggerHelpers('beforeRender');
			unset($name, $loadedHelpers, $helpers, $i, $helperNames, $helper);
		}
		
		extract($___dataForView, EXTR_SKIP);
		ob_start();
		
		$__element = $this->_element->findByName($___viewFn);
		eval('?>' . $__element['Element']['data'] . '<?');
		
		
		if ($loadHelpers === true) {
			$this->_triggerHelpers('afterRender');
		}

		$out = ob_get_clean();
		$caching = (
			isset($this->loaded['cache']) &&
			(($this->cacheAction != false)) && (Configure::read('Cache.check') === true)
		);

		if ($caching) {
			if (is_a($this->loaded['cache'], 'CacheHelper')) {
				$cache =& $this->loaded['cache'];
				$cache->base = $this->base;
				$cache->here = $this->here;
				$cache->helpers = $this->helpers;
				$cache->action = $this->action;
				$cache->controllerName = $this->name;
				$cache->layout = $this->layout;
				$cache->cacheAction = $this->cacheAction;
				$cache->cache($___viewFn, $out, $cached);
			}
		}
		return $out;
	}
	
	
	
}
?>

コントローラーに書く

var $view = 'dbelement';

ビューファイルは普通に↓で呼び出せる

<?php echo $this->element('login'); ?>
<?php echo $this->element('time'); ?>
<?php echo $this->element('time', array('cache' => '+2 days')); ?>
  • ちゃんと時計が表示される
  • キャッシュ設定すれば止まったまま