用户自定义
本章讲介绍一些开发过程中常用需要自定义的东西。
一、自定义404页面
一般比较完整的站点,都会有自定义的404页面,既美观统一、又能保持访问者不至于因为错误页面而退出网站。
比如说duowan.com的404页面,是一个坦克大战的小游戏,可以在线玩并且成绩还会进入排行榜,和其他网友一较高下。
对404错误页面的建议:
- 建议不要使用PHP动态页面,纯HTML页面会比较好。
- 具特色,但不能过于复杂的页面,保存页面可以快速载入和有鲜明的提示。
- 通常会进行一些引导,作为“找不到页面”的补充,但建议不要过多。
在sp框架中,自定义自己程序的404页面,也是很简单的事情。
打开protected/controller/BaseController.php,在BaseController类中,加入以下方法:
public static function err404($module, $controller, $action){
header("HTTP/1.0 404 Not Found");
exit;
}
当你访问到一个不存在的controller/action的时候,就会出现http 404的提示了。
当然你还可以做得更漂亮一点,比如说做个叫404.html的页面,放在模板目录里面。然后修改一下上面的err404()方法:
public static function err404($module, $controller, $action){
header("HTTP/1.0 404 Not Found");
$controlObj = new Controller;
$controlObj->display("404.html");
exit;
}
现在你就可以在404的时候显示你的404.html页面了。
这里不建议去掉header函数输出的404头,因为这样才比较符合一个404页面的规范,并且搜索引擎以及内容分发网络(CDN)等都不会误会成一个普通的页面(只是页面上写着404),从而引发一些没必要的问题。
另外exit也最好保留,因为404之后你就不需要再执行下去了。
二、全局位置
在后面准备讲自定义类库和自定义函数库的知识之前,我们最好能来了解一下关于程序的全局位置。
全局位置的作用一般是:
- 定义常量:定义在整个程序中使用到的静态常量,如路径的定义、数值的定义等。
- 载入文件:载入全局都要使用的类库/函数库php文件
- 执行某些代码:如进行应用程序配置的合并、执行全局函数,GZIP压缩或输出处理等。
- 全局性的预操作,如权限控制,菜单构造、全局跳转等。
在新版的sp框架里面,全局位置更为单一,因为我们认为全局位置就是一个控制专用的位置,所以它必须处在控制器的范畴内。
新版中我们加入了BaseController这个自带的用户类,它的位置刚好在Controller控制器父类和用户自定义控制器的继承链之间。这样使得BaseController既有普通的Controller的功能,也能覆盖到全部用户控制器之前进行操作。所以BaseController是比较适合当做全局位置的地方。
BaseController有一个初始化执行的方法,名为init(),它会在BaseController构造函数内执行,所以进入控制器后最先执行的位置。
全局定于和全局操作,就可以放在BaseController/init()里面执行。
对比来说,新版的init()和旧版直接使用控制器父类的构造函数,差别并不大。但是直接使用构造函数还是会不太优雅,所以新版加入了init()方法来代替。
三、自定义类库
在之前的快速入门教程中,我们已经讲述过,新版sp框架里面,自定义的类库实际上跟Model模型类一样,只要满足以下条件,都可以直接通过new语法来实例化:
- 类名和类文件名一致,当然也必须是大小写一致才行。
- 类文件放在protected下面的model、include、controller之一的目录内。
四、自定义函数库
用户自定义的函数,一般都是比较实用并且经常用到的一些函数集合,如加解密、分片下载、美化时间等函数。
所以我们一般会建议自定义的函数都放到一个函数库文件里面,在“全局位置”中引入该文件(如BaseController的init()函数),这样就在程序的大部分地方都可以轻松调用了——包括新版的模板引擎内。
是的,新版的模板引擎,已经不再需要“注册函数”才能在模板里面用函数了。
这里举个例子,我们为程序引入一个叫mydate()的函数。
<?php
// mydate函数
function mydate($time = null){
if( null == $time )$time = time(); // 默认是当前时间
if( $time > (time() - 3600) ){
return "刚才";
}elseif( $time > (time() - 3600 * 24) ){
return "今天";
}elseif( $time > (time() - 3600 * 24 * 2) ){
return "昨天";
}elseif( $time > (time() - 3600 * 24 * 3) ){
return "前天";
}else{
return date("Y-m-d H:s", $time);
}
}
?>
将以上代码保存到protected/include/functions.php里面。
functions.php文件和include目录都是不存在的,需要自行创建。
然后在BaseController的init()函数内,将它包含进来:
<?php
class BaseController extends Controller{
function init(){
require(APP_DIR.'/protected/include/functions.php');
}
}
?>
那么,在程序的控制器以及模板内,都可以正常使用mydate()函数了。
五、自定义错误处理
speedphp拥有标准的错误处理函数,在debug模式下会显示出现的错误,以及详细的错误的过程代码;而在部署模式下,则会直接使用error_log来记录错误信息,然后静默返回执行。
在部署模式的错误静默处理情况下,开发者应该及时关注服务器error_log日志,以便发现问题。
注意:自定义错误处理函数,以及包括speedphp的标准错误处理函数,都无法捕获到php核心错误。
当我们希望能自行控制错误处理时,可以通过配置$config[‘err_handler’]将错误处理转移到自定义函数内处理。
如在config.php内写入:
$config = array(
'err_handler' => 'hide_err'
);
function hide_err($msg, $traces) {
dump($msg);
dump($traces);
}
那么框架内捕捉到的错误,均会交给hide_err()函数来做处理。
开发者在hide_err()函数内,应自行通过$GLOBALS[‘debug’]的值,对部署模式和调试模式之间的差异进行分别处理。