TemplateLayout.php 4.34 KB
<?php

/**
 * 模板视图
 * 
 * @name TemplateLayout
 * @package library/Plugin
 * @copyright yoho.inc
 * @version 1.0 (2015-9-15 14:14:02)
 * @author fei.hong <fei.hong@yoho.cn>
 */
namespace Plugin;

use Yaf\View_Interface;
use Yaf\Dispatcher;
use Yaf\Application;

use Plugin\LightnCandy;

class TemplateLayout implements View_Interface
{
    
    /* 属性 */
    protected $_tpl_vars;
    protected $_tpl_dir;

    /**
     * 传递给视图变量
     * 
     * @param mixed $name
     * @param mixed $value
     */
    public function assign($name, $value = null)
    {
        $this->_tpl_vars[$name] = $value;
    }
    
    /**
     * 清除一个视图变量
     * 
     * @param mixed $name
     * @return void
     */
    public function clear($name = null)
    {
        if (isset($this->_tpl_vars[$name])) {
            unset($this->_tpl_vars[$name]);
        } else {
            $this->_tpl_vars = array();
        }
    }

    /**
     * 渲染视图模板,并直接输出到客户端
     * 
     * @param string $tpl
     * @param array $tpl_vars
     */
    public function display($tpl, $tpl_vars = array())
    {
        echo $this->render($tpl, $tpl_vars);
    }

    /**
     * 渲染视图模板
     * 
     * @param string $tpl
     * @param array $tpl_vars
     * @return string
     */
    public function render($tpl, $tpl_vars = array())
    {
        $request = Dispatcher::getInstance()->getRequest();
        $config = Application::app()->getConfig()->get('application');
        $tplExt = $config->template->ext;
        $viewPath = $config->template->path;
        $viewName = $viewPath . '/' . strtolower($request->module) . '/' . strtolower($request->controller) . '/' . $tpl . $tplExt;
        // 判断视图模板文件是否存在, 不存在则直接返回空
        if (!file_exists($viewName)) {
            return '';
        }
        
        // 合并通过assign传递的参数
        if (is_array($this->_tpl_vars)) {
            $tpl_vars = array_merge($this->_tpl_vars, $tpl_vars);
        }

        // 取得模板的最后修改时间戳
        $lastModifyTime = filemtime($viewName);
        // 使用MD5生成唯一的键名
        $makeKey = md5($viewName . strval($lastModifyTime));
        // 模板编译成PHP文件所存放的目录
        $compilePath = $config->template->compile;
        // 模板编译成PHP文件所存放的文件路径
        $compilePhp = $compilePath . '/' . $makeKey . '.php';
        
        // 已渲染过该模板,则直接引PHP文件
        if (is_readable($compilePhp)) {
            LightnCandy::getContext();
            $renderer = include($compilePhp);
        } 
        // 第一次渲染该模板的流程:取得模板内容 => 预编译成PHP函数 => 写入服务器生成PHP文件
        else {
            $template = file_get_contents($viewName, false, null);
            $phpStr = LightnCandy::compile($template, array(
                // DEBUG: LightnCandy::FLAG_RENDER_DEBUG | LightnCandy::FLAG_ERROR_EXCEPTION
                'flags' => LightnCandy::FLAG_RENDER_DEBUG | LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_MUSTACHE | LightnCandy::FLAG_HANDLEBARS, // 使用MUSTACHE和HANDLEBARS的模板格式
                'basedir' => array($config->template->partials), // 模板里使用 {{> partial_name}} 时查找的目录
                'fileext' => array($tplExt), // 允许查找文件的后缀
                'lcrun' => 'Plugin\LCRun3', // 指定编译模板的runtime
            ));
            // 文件流方式读取PHP方法
            $renderer = LightnCandy::prepare($phpStr);
            // 将编译过的函数写入PHP文件
            file_put_contents($compilePhp, $phpStr);
        }
        
        // 装载内容,调用PHP函数
        try {
            $result = $renderer($tpl_vars);
        } catch (Exception $e)  {
            $result = '';
        }
        
        return $result;
    }

    /**
     * 设置视图模板目录
     * 
     * @param string $path
     * @return boolean
     */
    public function setScriptPath($path)
    {
        $result = false;
        if (is_dir($path)) {
            $this->_tpl_dir = $path;
            $result = true;
        }
        return $result;
    }

    /**
     * 获取视图模板目录
     * 
     * @return string
     */
    public function getScriptPath()
    {
        return $this->_tpl_dir;
    }

}