在TP5中,模板里的include file里使用变量的解决方案

版权声明:可能不高端,但也是心血,原创不易,转载需注明出处 https://blog.csdn.net/Autumn_1/article/details/83064155

在一个项目中遇到一个需求,需要在模板文件上一层加一个文件,类似 dir/index/index.html这种东西,尴尬的是,这个dir是不固定的,所以我希望的是,在模板里能使用 {include file="$dir/index/index"},像什么{include file=$dir."/index/index"} 或者 {include file="{$dir}/index/index"} 或者 {include file="$dir.index/index"},还有什么单双引号拼接之类的都试过,然而并不支持。
所以我想到了下面几种种方式:
1.提前定义好

$dir=‘dir/index/index’

然后直接写在{include file="$dir"},但是这样就出现一个问题,我页面上那么多地方需要用到引入文件,不可能都定义一次,否定!
2.拼接引入文件,这样可以使用变量,但是不会被渲染,导致我引入文件里的变量等全部需要用原生PHP写,这改动对我来说太大了,否定!
3.改动框架源文件,让这里可以识别变量。然后我找到渲染模板替换文件,在根目录下的:thinkphp/library/think/Template.phpl里有个方法:

public function parse(&$content)
    {
        // 内容为空不解析
        if (empty($content)) {
            return;
        }
        // 替换literal标签内容
        $this->parseLiteral($content);
        // 解析继承
        $this->parseExtend($content);
        // 解析布局
        $this->parseLayout($content);
        // 检查include语法
        $this->parseInclude($content);
        // 替换包含文件中literal标签内容
        $this->parseLiteral($content);
        // 检查PHP语法
        $this->parsePhp($content);

        // 获取需要引入的标签库列表
        // 标签库只需要定义一次,允许引入多个一次
        // 一般放在文件的最前面
        // 格式:<taglib name="html,mytag..." />
        // 当TAGLIB_LOAD配置为true时才会进行检测
        if ($this->config['taglib_load']) {
            $tagLibs = $this->getIncludeTagLib($content);
            if (!empty($tagLibs)) {
                // 对导入的TagLib进行解析
                foreach ($tagLibs as $tagLibName) {
                    $this->parseTagLib($tagLibName, $content);
                }
            }
        }
        // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀
        if ($this->config['taglib_pre_load']) {
            $tagLibs = explode(',', $this->config['taglib_pre_load']);
            foreach ($tagLibs as $tag) {
                $this->parseTagLib($tag, $content);
            }
        }
        // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀
        $tagLibs = explode(',', $this->config['taglib_build_in']);
        foreach ($tagLibs as $tag) {
            $this->parseTagLib($tag, $content, true);
        }
        // 解析普通模板标签 {$tagName}
        $this->parseTag($content);

        // 还原被替换的Literal标签
        $this->parseLiteral($content, true);
        return;
    }

这里的 $this->parseInclude($content);就是引入相关功能代码!进入后是如下代码:

private function parseInclude(&$content)
    {
        $regex = $this->getRegex('include');
        $func  = function ($template) use (&$func, &$regex, &$content) {
            if (preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    $array = $this->parseAttr($match[0]);
                    $file  = $array['file'];
                    unset($array['file']);
                    // 分析模板文件名并读取内容
                    $parseStr = $this->parseTemplateName($file);
                    foreach ($array as $k => $v) {
                        // 以$开头字符串转换成模板变量
                        if (0 === strpos($v, '$')) {
                            $v = $this->get(substr($v, 1));
                        }
                        $parseStr = str_replace('[' . $k . ']', $v, $parseStr);
                    }
                    $content = str_replace($match[0], $parseStr, $content);
                    // 再次对包含文件进行模板分析
                    $func($parseStr);
                }
                unset($matches);
            }
        };
        // 替换模板中的include标签
        $func($content);
        return;
    }

其中的$parseStr = $this->parseTemplateName($file);就是在把file=""的内容放进去解析,OK,我们再进入看看:

private function parseTemplateName($templateName)
    {
        $array    = explode(',', $templateName);
        $parseStr = '';
        foreach ($array as $templateName) {
            if (empty($templateName)) {
                continue;
            }
            if (0 === strpos($templateName, '$')) {
                //支持加载变量文件名
                $templateName = $this->get(substr($templateName, 1));
            }
            $template = $this->parseTemplateFile($templateName);
            if ($template) {
                // 获取模板文件内容
                $parseStr .= file_get_contents($template);
            }
        }
        return $parseStr;
    }

好的,就是这里!下面还有变量相关的代码,有兴趣的朋友可以打印看看,这里不再赘述。我不改动源码,在这段代码前面加一点就行,代码如下:

$arr = explode('/',$templateName);
        $str = '';
        foreach($arr as $v){
            if(0 === strpos($v,'$')){
                $str .= $this->get(substr($v, 1)).'/';
            }else{
                $str .= $v.'/';
            }
        }
        $templateName = substr($str,0,-1);

原理很简单,就是把file里的内容经过"/"分割,然后循环判断是否为变量,是变量这去拿变量的值,然后重新拼接在一起。这个操作会让下面源码里的变量判断失效,不过没关系,我们在这里已经转化过了。我没有去动源码,因为怕引出更多问题。
测试一下,OK!
一点小东西,希望能帮到需要的朋友,如果大佬们有更好的方法,或者我这里有问题,都欢迎指导和指正!

猜你喜欢

转载自blog.csdn.net/Autumn_1/article/details/83064155
今日推荐