smarty太臃肿!手动原创一个视图模板引擎
smarty太臃肿!手动原创一个视图模板引擎
voyage1314 发表于4年前
smarty太臃肿!手动原创一个视图模板引擎
  • 发表于 4年前
  • 阅读 183
  • 收藏 0
  • 点赞 0
  • 评论 6
摘要: 当初搭云框架的时候,采用yaf+smarty,后来发现smarty实在太臃肿,做了很多php做的事(大部分不是我们需要的),后来决定去掉smarty,直接在页面写php。一段时间后发现太混乱了,没法维护,结果自己就写了一个模板引擎,能够满足常见的逻辑需求就OK。。考虑到正则效率有点低,所以大部分匹配替换使用的是php函数。
<?php
/**
 * 模板引擎
 *
 */
class View {
    //编译目录
    private $compile_dir = '/tmp/';
    //存储文本数组
    private $template_array;
    //文件路径
    private $file_name;
    //include行号
    private $INCLUDE;
    //if开始标签行号
    private $IF_START;
    //else行号
    private $IF_ELSE;
    //if结束标签行号
    private $IF_END;
    //foreach开始标签行号
    private $FOREACH_START;
    //foreach结束标签行号
    private $FOREACH_END;
    
    public function __construct($file_name) {
        $this->file_name = $file_name;
    }
    
    /**
     * 模板编译
     */
    public function complie() {
        //将文件以数组的形式输出
        $this->template_array = file($this->file_name);
        //查找include
        foreach ($this->template_array as $key => $value) {
            $template_array[$key] = trim($value);
            $mark = substr($template_array[$key], 0,8);
            if ($mark == '{include') 
                $this->INCLUDE[] = $key;
        }
        //include存在则合并包含文件
        if (isset($this->INCLUDE)) {
            $this->pregInclude();
            foreach ($this->template_array as $key => $value) {
                if (is_array($value)) {
                    foreach ($value as $k => $v) {
                        $include_array[] = $v;
                    }
                }
                else {
                    $include_array[] = $value;
                }
            }
        }
        else {
            $include_array = $this->template_array;
        }
        unset($this->template_array);
        unset($template_array);
        foreach ($include_array as $k => $v) {
            $array[$k] = trim($v);
            $mark = substr($array[$k], 0,4);
            switch ($mark) {
                //foreach开始
                case '{for':$this->FOREACH_START[] = $k;
                break;
                //foreach结束
                case '{/fo':$this->FOREACH_END[] = $k;
                break;
                //if开始
                case '{if ':$this->IF_START[] = $k;
                break;
                //else
                case '{els':$this->IF_ELSE[] = $k;
                break;
                //if结束
                case '{/if':$this->IF_END[] = $k;
                break;
            }
        }
        $this->template_array = $include_array;
        unset($include_array);
        /**
         * 转为php标签
         */
        if (isset($this->FOREACH_START)) {
            $this->pregForeachStart();
            $this->pregEnd($this->FOREACH_END);
        }
        if (isset($this->IF_START)) {
            $this->pregIfStart();
            $this->pregEnd($this->IF_END);
        }
        if (isset($this->IF_ELSE)) {
            $this->pregElse();
        }
        /**
         * 写入文件
         */
        $template_string = $this->pregString();
        $complie_file = basename($this->file_name); //产生缟译后的文件名
        $result = file_put_contents($this->compile_dir.'/view/'.$complie_file, $template_string);
        if (is_int($result)) 
            return $template_string;
        else return false;
    }
    /**
     * 合并include文件
     * @param string $key    :0
     * @param string $value :{include file="/xx/xx.phtml"}
     */
    private function pregInclude() {
        foreach ($this->INCLUDE as $value) {
            $tmp = explode("\"", $this->template_array[$value]);
            $path = "/yby/site/YAE/application/views$tmp[1]";
            if (!file_exists($path)) exit('文件不存在');
            $this->template_array[$value] = file($path);
        }
    }
    /**
     * 替换foreach开始标签
     * @param unknown $key
     * @param unknown $value
     */
    private function pregForeachStart() {
        foreach ($this->FOREACH_START as $line) {
            $value = $this->template_array[$line];
            /**
             * 分解foreach条件 "{foreach key=k value=data}"
             * $foreach_condition[0] = "{foreach" 
             * $foreach_condition[1] = "key=k"
             * $foreach_condition[2] = "data=$value}"
             */
            $foreach_condition = explode(' ', trim($value));
            $foreach_condition_data = rtrim($foreach_condition[2],'}');
            /**
             * $data = "data"
                * $val = "$value"
             */
            list($data,$val) = explode('=', $foreach_condition_data);
            /**
             * $key = "key"
             * $k = "k"
             */
            list($key,$k) = explode('=', $foreach_condition[1]);
            $replace = "<?php foreach($val as $".$k." => $"."$data) {?>";
            $this->template_array[$line] = $replace; 
        }
    }
    /**
     * 替换if开始标签
     * @param unknown $key
     * @param unknown $value
     */
    private function pregIfStart() {
        //$line 行号
        foreach ($this->IF_START as $line) {
            $value = $this->template_array[$line];
            /**
             * $if_condition = "$data.status == 0" or "$value == null" or "isset($value)"
             */
            $if_condition = substr(trim($value), 4);
            $if_condition = rtrim($if_condition,'}');
            $if_condition = explode(' ', $if_condition);
            $count = count($if_condition);
            switch ($count) {
                case 1:
                    $replace = "<?php if(".$if_condition[0].") { ?>";
                break;
                case 2:
                break;
                case 3:
                    $if_condition_data = explode('.', $if_condition[0]);
                    $num = count($if_condition_data);
                    $data = $if_condition_data[0];
                    for ($i = 1; $i < $num; $i++) {
                        $data .= "['$if_condition_data[$i]']";
                    }
                    $replace = "<?php if(".$data.$if_condition[1].$if_condition[2].") { ?>";
                break;
            }
            $this->template_array[$line] = $replace;
        }
    }
    /**
     * 替换结束标签
     * @param unknown $key
     */
    private function pregEnd($value) {
        foreach ($value as $line) {
            $replace = "<?php } ?>";
            $this->template_array[$line] = $replace;
        }
    }
    /**
     * 替换else
     * @param unknown $key
     */
    private function pregElse() {
        foreach ($this->IF_ELSE as $line) {
            /**
             * $if_condition[0] :"{else}" or "{elseif *** == ***}" or "{elseif isset(***)}"
             */
            $if_condition = trim($this->template_array[$line]);
            $if_condition = trim($if_condition,'{}');
            $if_condition = explode(' ', $if_condition);
            $count = count($if_condition);
            switch ($count) {
                case 1:
                    $replace = "<?php }else{ ?>";
                    break;
                case 2:
                    $replace = "<?php }elseif($if_condition[1]) { ?>";
                    break;
                case 4:
                    $if_condition_data = explode('.', $if_condition[1]);
                    $num = count($if_condition_data);
                    $data = $if_condition_data[0];
                    for ($i = 1; $i < $num; $i++) {
                        $data .= "['$if_condition_data[$i]']";
                    }
                    $replace = "<?php }elseif($data $if_condition[2] $if_condition[3]) { ?>";
                    break;
            }
            $this->template_array[$line] = $replace;
        }
    }

    /**
     * 直接输出字符串
     */
    private function pregString() {
        $template_string = implode('', $this->template_array);
        /**
         * $matches[0][$i] : "{$data.app_name}"
         */
        preg_match_all("/\{(\\$(\b\w+\b\.)+\b\w+\b)\}|\{(\\$\b\w+\b)\}/", $template_string, $matches);
        if (!empty($matches[0])) {
            foreach ($matches[0] as $key => $val) {
                $value = trim($val,'{}');
                $data = explode('.', $value);
                $count = count($data);
                $result = $data[0];
                for ($i = 1; $i < $count; $i++) {
                    $result .= "['$data[$i]']";
                }
                $replace = "<?php echo $result;?>";
                $template_string = str_replace($val, $replace, $template_string);
            }
        }
        return $template_string;
    }
    
    public function __destruct() {
        unset($this->template_array);
    }
}




共有 人打赏支持
粉丝 8
博文 9
码字总数 6947
评论 (6)
月影又无痕
就别用这种东西误导初学者了吧
哈哈__哈哈
php为啥需要模板引擎,本身就是一个模板引擎。
voyage1314

引用来自“邓攀”的评论

php为啥需要模板引擎,本身就是一个模板引擎。

那不懂php语法的前端如何去写逻辑
哈哈__哈哈

引用来自“voyage1314”的评论

引用来自“邓攀”的评论

php为啥需要模板引擎,本身就是一个模板引擎。

那不懂php语法的前端如何去写逻辑

我觉得一个mvc的即可,比如我用zend framework就在view写那些拼接字符串的工作,再搞一个smarty就有点慢而且不值得了
哈哈__哈哈

引用来自“voyage1314”的评论

引用来自“邓攀”的评论

php为啥需要模板引擎,本身就是一个模板引擎。

那不懂php语法的前端如何去写逻辑

什么逻辑,逻辑肯定都是后端去写啊。。跟前段没关系,
overlords

引用来自“邓攀”的评论

php为啥需要模板引擎,本身就是一个模板引擎。

真心觉得没意思,php本身就是混血的,中间再来一个无聊
×
voyage1314
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: