文档章节

smarty太臃肿!手动原创一个视图模板引擎

voyage1314
 voyage1314
发布于 2013/12/24 16:33
字数 860
阅读 190
收藏 0
<?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);
    }
}




© 著作权归作者所有

共有 人打赏支持
voyage1314
粉丝 7
博文 9
码字总数 6947
作品 0
杨浦
程序员
加载中

评论(6)

overlords
overlords

引用来自“邓攀”的评论

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

真心觉得没意思,php本身就是混血的,中间再来一个无聊
哈哈__哈哈
哈哈__哈哈

引用来自“voyage1314”的评论

引用来自“邓攀”的评论

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

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

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

引用来自“voyage1314”的评论

引用来自“邓攀”的评论

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

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

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

引用来自“邓攀”的评论

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

那不懂php语法的前端如何去写逻辑
哈哈__哈哈
哈哈__哈哈
php为啥需要模板引擎,本身就是一个模板引擎。
月影又无痕
月影又无痕
就别用这种东西误导初学者了吧
构建mvc框架学习

做了那么久PHP开发,开始尝试去做一个简单的mvc框架。 一、首先确定目录结构 由于不太想弄得太复杂的结构,因此,将所有的目录存放于libs中,项目根目录只留一个index.php以及config.php,形...

AlpherJang
2016/03/03
89
0
除了smarty还有啥比较靠谱的php模板引擎

smarty太臃肿,想找一个比较轻巧的模板引擎,执行效率高点的,文件数量不超过10个。

leo108
2013/08/17
2.9K
8
PHP应用框架--SpeedPHP

SpeedPHP是一款全功能的国产PHP框架应用系统,速度飞快,上手容易,是最适合初学者的PHP框架,以“快速开发、快速学习、快速执行”为理念,带你轻松进入PHP高手的行列。 SpeedPHP 3正式版发布...

SpeedPHP
2009/12/07
6.2K
2
基于 PHP 的企业内容管理系统--MyfCMS

闵益飞内容管理系统英文缩写MyfCMS,采用PHP5+MySQL作为技术基础进行开发。MyfCMS的模板引擎使用了当前最流行的smarty模板引擎,MVC框架采用了自己研发的MyfMVC框架(特轻量级的PHPMVC框架,...

feiyue
2012/05/21
8.5K
0
PHP 模板引擎SMARTY 原理

一、MVC需要模板 MVC最早是在SmallTalk语言的开发过程中总结出的一种设计模式,MVC分别代表了"模型"、"视图"和"控制",目的就是让不同的开发角色在大中型项目中各司其职。在网络应用程序的开...

酒肉穿肠过
2013/09/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Cloud Gateway真的有那么差吗?

前言 Spring Cloud从一开始最受大家质疑的就是网关性能,那是由于Spring Cloud最初选择了使用Netflix几年前开源的Zuul作为基础,而高性能版的Zuul 2在经过了多次跳票之后,对于Spring这样的整...

Java小铺
43分钟前
1
0
SpringBoot远程调试,远程debug你的线上项目

开发环境中代码出错了,可以利用IDE的debug功能来进行调试。那线上环境出错呢? 一、假设我们的项目是部署在tomcat中,那我们就需要对tomcat进行一定对配置,配置如下。 1. windows系统中,找...

nonnetta
48分钟前
0
0
JAVA秒杀优化方向

秒杀优化方向 将请求尽量拦截在系统上游:传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,几乎所有请求都超时,流量虽大,下单成功的有效流量甚小,我们可以通过限流、...

小贱是个程序员
56分钟前
0
0
C# 统计字符串中大写字母和小写字母的个数

static void Main() { int count1 = 0; int count2 = 0; Console.WriteLine("请输入字符串"); string str = Convert.ToString(Consol......

熊二的爸爸是谁
58分钟前
0
0
分布式服务框架之远程通讯技术及原理分析

在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是...

老道士
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部