thinkcmf5更新模板代码分析,解决模板配置json出错导致数据库保存的配置项内容丢失问题

 private function updateThemeFiles($theme, $suffix = ‘html‘)
    {
        $dir                = ‘themes/‘ . $theme;
        $themeDir           = $dir;
        $tplFiles           = [];
        $root_dir_tpl_files = cmf_scan_dir("$dir/*.$suffix");       //默认情况下返回 模板目录(w0s目录)下的所有html文件名数组
        foreach ($root_dir_tpl_files as $root_tpl_file) {
            $root_tpl_file           = "$dir/$root_tpl_file";
            $configFile              = preg_replace("/\.$suffix$/", ‘.json‘, $root_tpl_file);  //获取当前$root_tpl_file对应json文件名 例如 index.json
            $root_tpl_file_no_suffix = preg_replace("/\.$suffix$/", ‘‘, $root_tpl_file);     //获取对应文件名无后缀
            if (is_file($root_tpl_file) && file_exists_case($configFile)) {  //当前$root_tpl_file(例如:index.html)是个文件,并且index.json存在
                array_push($tplFiles, $root_tpl_file_no_suffix);  //把文件名存起来,不包含后缀。例如:index
            }
        }
        $subDirs = cmf_sub_dirs($dir);   //子目录下文件,是不是只支持两级目录????
        foreach ($subDirs as $dir) {
            $subDirTplFiles = cmf_scan_dir("$dir/*.$suffix");
            foreach ($subDirTplFiles as $tplFile) {
                $tplFile         = "$dir/$tplFile";
                $configFile      = preg_replace("/\.$suffix$/", ‘.json‘, $tplFile);
                $tplFileNoSuffix = preg_replace("/\.$suffix$/", ‘‘, $tplFile);
                if (is_file($tplFile) && file_exists_case($configFile)) {
                    array_push($tplFiles, $tplFileNoSuffix);
                }
            }
        }

        foreach ($tplFiles as $tplFile) {  //遍历所有文件json文件
            $configFile = $tplFile . ".json";
            $file       = preg_replace(‘/^themes\/‘ . $theme . ‘\//‘, ‘‘, $tplFile);
            $file       = strtolower($file);
            $config     = json_decode(file_get_contents($configFile), true);
            $findFile   = Db::name(‘theme_file‘)->where([‘theme‘ => $theme, ‘file‘ => $file])->find();
            $isPublic   = empty($config[‘is_public‘]) ? 0 : 1;
            $listOrder  = empty($config[‘order‘]) ? 0 : floatval($config[‘order‘]);
            $configMore = empty($config[‘more‘]) ? [] : $config[‘more‘];
            $more       = $configMore;

            if (empty($findFile)) {   //在数据表theme_file没有找到该模板 则插入
                Db::name(‘theme_file‘)->insert([
                    ‘theme‘       => $theme,
                    ‘action‘      => $config[‘action‘],
                    ‘file‘        => $file,
                    ‘name‘        => $config[‘name‘],
                    ‘more‘        => json_encode($more),
                    ‘config_more‘ => json_encode($configMore),
                    ‘description‘ => $config[‘description‘],
                    ‘is_public‘   => $isPublic,
                    ‘list_order‘  => $listOrder
                ]);
            } else { // 更新文件
                $moreInDb = json_decode($findFile[‘more‘], true);    //从数据库里读出来的more字段
                $more     = $this->updateThemeConfigMore($configMore, $moreInDb); //$configMore从index.json文件里读的json,$moreInDb从数据库里读的more字段的值
                Db::name(‘theme_file‘)->where([‘theme‘ => $theme, ‘file‘ => $file])->update([
                    ‘theme‘       => $theme,
                    ‘action‘      => $config[‘action‘],
                    ‘file‘        => $file,
                    ‘name‘        => $config[‘name‘],
                    ‘more‘        => json_encode($more),            //json文件里有并且从数据里取值以后,这里如果$configMore没有正确读取的话应该是返回了一个空值,没有保存成功
                    ‘config_more‘ => json_encode($configMore),      //从index.json来的配置文件
                    ‘description‘ => $config[‘description‘],
                    ‘is_public‘   => $isPublic,
                    ‘list_order‘  => $listOrder
                ]);
            }
        }

        // 检查安装过的模板文件是否已经删除
        $files = Db::name(‘theme_file‘)->where([‘theme‘ => $theme])->select();

        foreach ($files as $themeFile) {
            $tplFile           = $themeDir . ‘/‘ . $themeFile[‘file‘] . ‘.‘ . $suffix;
            $tplFileConfigFile = $themeDir . ‘/‘ . $themeFile[‘file‘] . ‘.json‘;
            if (!is_file($tplFile) || !file_exists_case($tplFileConfigFile)) {
                Db::name(‘theme_file‘)->where([‘theme‘ => $theme, ‘file‘ => $themeFile[‘file‘]])->delete();
            }
        }
    }
/**
 * 替代scan_dir的方法
 * @param string $pattern 检索模式 搜索模式 *.txt,*.doc; (同glog方法)
 * @param int $flags
 * @param $pattern
 * @return array
 */
function cmf_scan_dir($pattern, $flags = null)
{
    $files = glob($pattern, $flags);   //函数返回匹配指定模式的文件名或目录。该函数返回一个包含有匹配文件 / 目录的数组。如果出错返回 false。http://www.w3school.com.cn/php/func_filesystem_glob.asp
    if (empty($files)) {
        $files = [];
    } else {
        $files = array_map(‘basename‘, $files);   //函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 basename  函数返回路径中的文件名部分
    }

    return $files;     //指定规则的文件的文件名数组,在更新模板时,返回的是所有.html的文件名,带扩展名  http://www.w3school.com.cn/php/func_filesystem_basename.asp。
}
 private function updateThemeConfigMore($configMore, $moreInDb)
    {

//echo empty($configMore);
// print_r($configMore); 
// return;

if (!empty($configMore[‘vars‘])) {
            foreach ($configMore[‘vars‘] as $mVarName => $mVar) {
                if (isset($moreInDb[‘vars‘][$mVarName][‘value‘]) && $mVar[‘type‘] == $moreInDb[‘vars‘][$mVarName][‘type‘]) {
                    $configMore[‘vars‘][$mVarName][‘value‘] = $moreInDb[‘vars‘][$mVarName][‘value‘];   //数据库里有这个vars,并且类型一样,则更新这个值到配置文件数组里。

                    if (isset($moreInDb[‘vars‘][$mVarName][‘valueText‘])) {
                        $configMore[‘vars‘][$mVarName][‘valueText‘] = $moreInDb[‘vars‘][$mVarName][‘valueText‘];
                    }
                }
            }
        }

        if (!empty($configMore[‘widgets‘])) {
            foreach ($configMore[‘widgets‘] as $widgetName => $widget) {

                if (isset($moreInDb[‘widgets‘][$widgetName][‘title‘])) {
                    $configMore[‘widgets‘][$widgetName][‘title‘] = $moreInDb[‘widgets‘][$widgetName][‘title‘];
                }

                if (isset($moreInDb[‘widgets‘][$widgetName][‘display‘])) {
                    $configMore[‘widgets‘][$widgetName][‘display‘] = $moreInDb[‘widgets‘][$widgetName][‘display‘];
                }

                if (!empty($widget[‘vars‘])) {
                    foreach ($widget[‘vars‘] as $widgetVarName => $widgetVar) {

                        if (isset($moreInDb[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘value‘]) && $widgetVar[‘type‘] == $moreInDb[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘type‘]) {
                            $configMore[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘value‘] = $moreInDb[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘value‘];

                            if (isset($moreInDb[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘valueText‘])) {
                                $configMore[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘valueText‘] = $moreInDb[‘widgets‘][$widgetName][‘vars‘][$widgetVarName][‘valueText‘];
                            }
                        }

                    }
                }

            }
        }

        return $configMore;
    }

问题关键在函数  updateThemeConfigMore($configMore, $moreInDb);   如果json文件有语法错误,$configMore没有正确读取。可能造成配置丢失。

在函数updateThemeConfigMore开头加如下代码输出json生成的数组

echo empty($configMore)."\n";
print_r($configMore); 
return;

模板更新,当json文件有语法错误(如少一个逗号)时,$configMore的值是空数组,empty($configMore)值返回1。

themes/w0s/portal/index
1

Array
(
)

解决方案 updateThemeFiles函数里增加对json转换结果的判断,转换成功再更新数据库。

private function updateThemeFiles($theme, $suffix = ‘html‘)
    {
        $dir                = ‘themes/‘ . $theme;
        $themeDir           = $dir;
        $tplFiles           = [];
        $root_dir_tpl_files = cmf_scan_dir("$dir/*.$suffix");
        foreach ($root_dir_tpl_files as $root_tpl_file) {
            $root_tpl_file           = "$dir/$root_tpl_file";
            $configFile              = preg_replace("/\.$suffix$/", ‘.json‘, $root_tpl_file);
            $root_tpl_file_no_suffix = preg_replace("/\.$suffix$/", ‘‘, $root_tpl_file);
            if (is_file($root_tpl_file) && file_exists_case($configFile)) {
                array_push($tplFiles, $root_tpl_file_no_suffix);

            }
        }
        $subDirs = cmf_sub_dirs($dir);
        foreach ($subDirs as $dir) {
            $subDirTplFiles = cmf_scan_dir("$dir/*.$suffix");
            foreach ($subDirTplFiles as $tplFile) {
                $tplFile         = "$dir/$tplFile";
                $configFile      = preg_replace("/\.$suffix$/", ‘.json‘, $tplFile);
                $tplFileNoSuffix = preg_replace("/\.$suffix$/", ‘‘, $tplFile);
                if (is_file($tplFile) && file_exists_case($configFile)) {
                    array_push($tplFiles, $tplFileNoSuffix);
                }
            }
        }

        foreach ($tplFiles as $tplFile) {
            $configFile = $tplFile . ".json";
            $file       = preg_replace(‘/^themes\/‘ . $theme . ‘\//‘, ‘‘, $tplFile);
            $file       = strtolower($file);
            $config     = json_decode(file_get_contents($configFile), true);
            $findFile   = Db::name(‘theme_file‘)->where([‘theme‘ => $theme, ‘file‘ => $file])->find();
            $isPublic   = empty($config[‘is_public‘]) ? 0 : 1;
            $listOrder  = empty($config[‘order‘]) ? 0 : floatval($config[‘order‘]);
            $configMore = empty($config[‘more‘]) ? [] : $config[‘more‘];
            $more       = $configMore;

            //json没有转换成功就不更新数据库
            if(!empty($config)){
                if (empty($findFile)) {
                    Db::name(‘theme_file‘)->insert([
                        ‘theme‘       => $theme,
                        ‘action‘      => $config[‘action‘],
                        ‘file‘        => $file,
                        ‘name‘        => $config[‘name‘],
                        ‘more‘        => json_encode($more),
                        ‘config_more‘ => json_encode($configMore),
                        ‘description‘ => $config[‘description‘],
                        ‘is_public‘   => $isPublic,
                        ‘list_order‘  => $listOrder
                    ]);
                } else { // 更新文件
                    $moreInDb = json_decode($findFile[‘more‘], true);
                    //echo "\n".$tplFile."\n";
                    $more     = $this->updateThemeConfigMore($configMore, $moreInDb);
                    //echo empty($more)."\n";

                    Db::name(‘theme_file‘)->where([‘theme‘ => $theme, ‘file‘ => $file])->update([
                        ‘theme‘       => $theme,
                        ‘action‘      => $config[‘action‘],
                        ‘file‘        => $file,
                        ‘name‘        => $config[‘name‘],
                        ‘more‘        => json_encode($more),
                        ‘config_more‘ => json_encode($configMore),
                        ‘description‘ => $config[‘description‘],
                        ‘is_public‘   => $isPublic,
                        ‘list_order‘  => $listOrder
                    ]);

                }
            }
        }
时间: 2024-10-05 20:20:37

thinkcmf5更新模板代码分析,解决模板配置json出错导致数据库保存的配置项内容丢失问题的相关文章

kafka没配置好,导致服务器重启之后,topic丢失,topic里面的消息也丢失

转,原文:https://blog.csdn.net/zfszhangyuan/article/details/53389916 ------------------------------------------------ 这个问题,在线上集群环境一般不容易出现,因为相关的日志文件参数都已经配置好了,而且经受住时间的的验证了. 作为新手,我在本地配置了一个单机kafka,用得是kafka自带的zookeeper服务. kafka安装很简单如下: 1).下载kafka: wget http:/

Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datasheet会把pin controller的内容放入GPIO controller的章节中),主要功能包括: (1)pin multiplexing.基于ARM core

Android Studio 模板用法与自定义模板

本文gif图比较多,可能会导致页面加载缓慢,请大家耐心等待 今天我们来学习下Android Studio这款软件的一些秘密,这些就是Template,就是我们输出一些特定的字符就可以实现自动编写一大堆代码,额,什么意思了?下面还是看图来理解吧! Live Template 这种模板用法就是输入特定字符,按下Tab键即可,此键可自定义设置 在方法中输入"Toast"并按下Tab键 快速编写TAG,在类中输入"logt"并按下Tab键 常量的编写,详细见图 输出语句的书

模板与泛型编程——定义模板

一.定义模板 1.函数模板 模板定义以关键字template开始,后跟一个模板参数列表,这是一个逗号分隔的一个或多个模板参数的列表,用<>括起来.在模板定义中,模板参数列表不能为空.模板参数表示在类或函数定义中用到的类型或值.当使用模板时,我们(隐式地或显式地)指定模板实参,将其绑定到模板参数上. 1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algo

ecshop新版不能在模板文件.dwt和.lbi中直接添加php代码的解决方法

ecshop新版不能在模板文件.dwt和.lbi中直接添加php代码了,为什么呢? 因为直接在模板中加入php函数和代码,没有经过过滤,容易造成安全隐患.程序源码安全是非常重要的. 不过如果有朋友希望能在模板文件中直接加入php代码,怎么办呢? 其实,只需要改动一个文件,即includes/cls_template.php 打开此文件,找到函数 function fetch_str($source) 在此函数中找到,大概在288行 if(preg_match_all('~(<\?(?:\w+|=

Android Studio 配置快速生成模板代码

前言 Android studio 有提供快速生成模板代码的功能,其实这个功能也可以自定义配置.此篇博客将讲解如何使用此功能 进入Settings 选择 Editor > Live Templates 创建一个自己的组 为了不与Android studio已经自带的模型代码混淆,我们创建一个自己的组来管理自己的模板代码,请看下图: 下图点击 + 号 ,有2个选择 1.第一个选择是在当前组里新建一个模板代码 2.第二个就是生成一个组,我已经创建了一个叫user的组 编辑代码模板 下图就是生成模板代

KMP算法的定义及KMP练手题 HDU 1711 Number Sequence (我的模板代码)

题意:就是要你来找出b数组在a数组中最先匹配的位置,如果没有则输出-1 思路:直接KMP算法(算法具体思想这位牛写的不错http://blog.csdn.net/v_july_v/article/details/7041827) AC代码: #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> using namespace std; #define maxn 100

模板代码 - 列表和下拉刷新

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD

inputstream和outputstream读写数据模板代码

//读写数据模板代码 byte buffer[] = new byte[1024]; int len=0; while((len=in.read(buffer))>0){ out.write(buffer,0,len); }