ThinkPHP3.2.3静态缓存的使用

当前位置:首页 » PHP
In 笔记  @2018-05-10

静态缓存可以大幅提升网站、接口的访问速度,对提升用户体验非常有帮助,刚好项目上也遇到这样的需求,在ThinkPHP3.2.3中实现前台页面静态缓存。

原理

静态缓存也就是将动态语言查询数据库然后渲染后的页面直接转换成文件(或者json)存储起来,当用户访问的时候,直接呈现给用户即可。

缓存前:

  • 根据用户请求页面解析到对应控制器、方法;
  • 查询数据库取出数据;
  • 数据处理;
  • 将数据渲染到模版输出;

缓存后:

  • 根据用户请求定位到静态文件;
  • 直接输出静态文件;

静态缓存通过简化处理流程(特别是连接数据库读取数据和数据处理),是可以大幅提升访问速度的。

实现步骤

1. 缓存配置:

在需要缓存的模块配置文件(如\Application\Home\Conf\config.php)中加入静态缓存配置:

    // 静态缓存配置
    'HTML_CACHE_ON'     =>    true,       // 开启静态缓存
    'HTML_CACHE_TIME'   =>    3600,       // 全局静态缓存有效期(秒)
    'HTML_FILE_SUFFIX'  =>    '.html',    // 设置静态缓存文件后缀
    'HTML_CACHE_RULES'  =>     array(     // 定义静态缓存规则
        // 定义整个文章控制器
        // 'Article:'      =>       'Article/{:action}_{id}',
        // 对商品进行缓存
        // 'Product:plist' =>       'Product/plist_{id}_{pid}',
        // 对单个操作进行缓存
        // 'Index:index'   =>       'Index/index',
        // 对Index控制器的所有操作缓存
        'Index:'           =>       'Index/{:action}_{id}',
        // 对Download控制器的所有操作缓存
        'Download:'        =>       'Download/{:action}_{id}',
        // 对Product控制器的所有操作缓存并设置缓存过期时间为7200秒
        'Product:'         =>       array('Product/{:action}_{id}', '7200'),
    ),

还有更多的静态缓存规则设置参考请官方文档。

2. 更新缓存

大部分情况下,我们不需要更新缓存,因为缓存到了缓存有效期就会自动失效,但有时候,修改模版布局,修改栏目或者更新文章后,需要马上更新缓存以便用户看到的是最新的效果,就需要在后台设置一个更新缓存的功能。

更新缓存的操作update_cache,当道控制器中供使用,其中HTML_PATHThinkPHP3.2.3定义的静态文件目录,默认是APP_PATH . 'Html/'

public function update_cache(){
    // 更新静态缓存文件
    if(del_file_under_dir(HTML_PATH)){
        $response = encode_return_data(0, '更新静态缓存成功');
    }else{
        $response = encode_return_data(10006, '更新静态缓存失败');
    }
    $this->ajaxReturn($response);
}

删除文件夹内的文件通用方法del_file_under_dir(),这个放到function.php

/**
 * 循环删除目录下的所有文件
 * @Author      hsu1943
 * @DateTime    2018-05-04T10:47:33+0800
 * @param    string                    $dirName 目录
 * @return   boolean                            是否删除成功
 */
function del_file_under_dir($dirName){
    if($handle = opendir( "$dirName" )) {
        while(false !== ($item = readdir($handle))){
            if($item != "." && $item != ".."){
                if(is_dir("$dirName/$item")){
                    del_file_under_dir("$dirName/$item");
                }else{
                    try {
                        unlink("$dirName/$item");
                    } catch (\Exception $e) {
                        echo $e->getMessage();
                    }
                }
            }
        }
        closedir($handle);
        return true;
    }else{
        return false;
    }
}
标签: , ,   评论: 抢沙发 

ThinkPHP3.2.3查询多次JOIN同一张表的处理

当前位置:首页 » PHP
In 笔记  @2018-05-09

问题:

在项目开发中遇到问题,要查询的一张主表post中有两个字段都关联了user表的id,需要取出useruser_name字段,那么应该怎么查询呢?

解决:

$posts_list = M()
    ->table('gc_post P')
    ->join('gc_user U ON P.author_id=U.id')
    ->join('gc_user U_M ON P.mentor_id=U_M.id')
    ->field('P.id, P.title, U.user_name as author_name, U_M.user_name as mentor_name,')
    ->order('P.gc_order desc')
    ->select();

这里是在ThinkPHP3.2.3下开发,给一张表取不同的别名,多次JOIN查询就可以正常取到数据了。

标签: , , ,   评论: 抢沙发 

ThinkPHP 3.2.3 实现前台多语言切换

当前位置:首页 » PHP
In 笔记  @2018-04-23

由于公司项目需要,多个客户有开发双语站点的需求,又由于下载来的CMS二次开发起来很费时间,项目差异导致每次使用得再来一次,加上前人留下来的东西无法整合进去,于是前端时间基于ThinkPHP3.2.3写了一套CMS系统,就将平时工作用户需求很高的一些功能整合进去了,其中一个功能就是这个中英文的切换。

思路

简单的思路,用户第一次进来默认中文,当用户点击了前台的中英文切换,将用户的选择的语言存储到cookie,加载页面的时候读取cookie中的语言设置并将其作为变量传给前台供模版渲染使用。

步骤

  1. /Application/Common/Conf的配置文件config.php文件中开启多语言功能;
    // 多语言包开启
    'LANG_SWITCH_ON'    => true, // 开启多语言
    'LANG_AUTO_DETECT'  => true, // 自动侦测语言
    'DEFAULT_LANG'      => 'zh-cn', // 默认语言
    'LANG_LIST'         => 'zh-cn, en-us', // 允许的语言列表
    'VAR_LANGUAGE'      => 'lang', // 默认语言切换变量
  1. /Application/Common/Conf下一个文件命名为tags.php,代码如下:
<?php 
/**
 * 多语言切换使用
 */
return array(
    'app_begin' => array('Behavior\CheckLangBehavior'),
)
?>
  1. /Application/Home/新建Lang文件夹,新建语言文件zh-cn.phpen-us.php,这里的翻译是提供给模版或者后台的L方法使用,这里可以放一些前端模版中除正文标题等数据库录入的中英文以外的翻译短语。
<?php
// zh-cn.php
return array(
    '示例'=>'我是中文',
    '测试'=>'我是测试',
    '首页'=>'首页',
    '404错误' => '404错误',
    '上一篇'=>'上一篇',
    '下一篇'=>'下一篇',
    '没有更多文章了'=>'没有更多文章了',
    '您现在的位置'=>'您现在的位置',
);
?>
<?php 
// en-us.php
return array(
    '示例'=>'English Page',
    '测试'=>'This is a test',
    '首页'=>'Home Page',
    '404错误'=>'404 NOT FOUND',
    '上一篇'=>'Prev',
    '下一篇'=>'next',
    '没有更多文章了'=>'No More Post',
    '您现在的位置'=>'current page',
);
?>
  1. 在能提供前台访问的控制器中写一个切换语言的接口,我这里放在/Application/Home/Controller/IndexController中取名lang()
    /**
     * 语言切换
     * @method GET 
     * @param string $lang 'cn' || 'en'
     * @Author       hsu1943
     * @DateTime     2018-04-09T15:44:27+0800
     * @return   
     */
    public function lang(){
        switch(I('get.lang')){
            case 'cn':
                cookie('think_language',null);
                cookie('think_language','zh-cn'); 
                break;
            case 'en':
                cookie('think_language',null);
                cookie('think_language','en-us');
                break;
        }
    }
  1. 在前台模版文件中添加切换按钮HTML代码;
<!-- 多语言切换 -->
<div class="lang">
    <a class="langBtn" lang="cn" href="javascript:void(0);">中文</a>
    <a class="langBtn" lang="en" href="javascript:void(0);">ENGLISH</a>
</div>
  1. HTML代码加上添加异步请求的JS代码,完成多语言切换功能;
var url = 'http://www.test.com/index.php/Home/Index/lang';
//中英文切换
$('.langBtn').on('click', function(){
    var data={'lang':$(this).attr('lang')}
    $.get(url, data, function(e){
        location.reload();
    })
})

至此,基于ThinkPHP3.2.3实现了多语言切换的功能了,当然,文章主要内容标题这些需要后台来添加的内容是需要存多语言版本到数据库,我在使用的时候是输出到模版的时候取出全部语言的内容,然后在输出的通过后台告诉我的当前用户选择的是什么语言,我就输出什么语言的内容,当然你也可以在查询的时候就先判断语言,然后查询该语言对应的内容输出即可;

2018-08-10更新

ThinkPHP在这里面有个坑,第一次访问的人没有cookie,理论上应该按照配置文件中DEFAULT_LANG来加载,但仔细看Behavior\CheckLangBehavior中的源码发现,当你的url中没有带语言变量,并且cookie('think_language')为空的时候,会去检测$_SERVER['HTTP_ACCEPT_LANGUAGE'],而也就是浏览器接受的语言,然而浏览器的这个语言(我用的是Chrome)是zh-CN或者en-US这样的带有大写的,然后把这个值存到cookie中,导致你的前台通过这个参数是否是zh-cn会失败,导致逻辑上出错。

解决方案一:

\ThinkPHP\Library\Behavior\CheckLangBehavior.class.php文件中:

elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){// 自动侦测浏览器语言
    preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
        $langSet = $matches[1];
        cookie('think_language',$langSet,3600);
    }

修改为:

elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){// 自动侦测浏览器语言
    preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
        $langSet = $matches[1];
        cookie('think_language',strtolower($langSet),3600);
    }

解决方案二:

cookie中取出来作模版语言设置参数的时候,将这个参数转换为小写即可。

// 多语言
$this->page_info['lang'] = strtolower(cookie('think_language'));
标签: , , ,   评论: 抢沙发