1.不要使用相对路径
常常会看到:
require_once('../../lib/some_class.php');
该方法有很多缺点:它首先查找指定的php包含路径,,然后查找当前目录.因此会检查过多路径。如果该脚本被另一目录的脚本包含,它的基本目录变成了另一脚本所在的目录。另一问题:当定时任务运行该脚本,它的上级目录可能就不是工作目录了。
因此最佳选择是使用绝对路径:
define('ROOT' , '/var/www/project/');
require_once(ROOT . '../../lib/some_class.php');
我们定义了一个绝对路径, 值被写死了. 我们还可以改进它. 路径 /var/www/project 也可能会改变, 那么我们每次都要改变它吗? 不是的, 我们可以使用__FILE__常量, 如:
define('ROOT' , pathinfo(__FILE__, PATHINFO_DIRNAME));
require_once(ROOT . '../../lib/some_class.php');
现在, 无论你移到哪个目录, 如移到一个外网的服务器上, 代码无须更改便可正确运行.
2.不要直接在程序中使用 require, include, include_once, required_once
如:require_once('lib/Database.php');
这种写法相当混乱. 应该更灵活点. 应编写个类文件. 例如:
class loader {
/**
* 加载模块下的类文件,类名需与文件中定义的相同、不带Class,但类的实际文件名全部小写
* 如:
* loader::importAppLib('mall', 'CMS');
* /root_path/mall/framework/libraries/cms.class.php
*
* @param string $module
* @param string $classname
* @param string $ext
* @return boolean 如果导入后,类不存在也会返回false
*/
public static function importAppLib($module, $classname, $ext = '.class.php') {
$result = self::importByApp($module, "libraries." . strtolower($classname), $ext);
if (!$result) {
return FALSE;
}
return class_exists($classname . 'Class', FALSE);
}
/**
* 加载模块下的函数库文件
* 如:
* loader::importAppFunc('mall', 'search');
* /root_path/mall/framework/function/search.php
* @param string $module
* @param string $file
* @param string $ext
* @return boolean
*/
public static function importAppFunc($module, $file, $ext = '.php') {
return self::importByApp($module, "function.{$file}", $ext);
}
/**
* 按模块,加载类库文件
* 如:
* loader::importByApp('mall', 'framework.libraries.CMS', '.class.php');
* /root_path/mall/framework/libraries/CMS.class.php
*
* loader::importByApp('mall', 'model.User');
* /root_path/mall/model/User.php
* @param string $module
* @param string $file
* @param string $ext
* @return boolean
*/
public static function importByApp($module, $file, $ext = '.php') {
return self::import("{$module}.framework.{$file}", $ext);
}
/**
* 通用的文件加载,在系统范围内,加载类、库的文件
* @param string $file 类库文件
* 需要带上相对于系统根目录的路径,目录之间以.分隔,如 mall.framework.function.xxx 大小写敏感
* @param string $ext 文件后缀名如.inc、.class.php、.php等,默认为.php
* @return boolean
*/
public static function import($file, $ext = '.php') {
if (strstr($file, '.')) {
$file = str_replace('.', DIRECTORY_SEPARATOR, $file);
}
$_file = realpath(BASE_CORE_PATH . '/../' . $file . $ext);
if (!file_exists($_file)) {
return false;
}
require_once $_file;
return true;
}
}
3.小心处理大数组
对于大的数组和字符串, 必须小心处理. 常见错误是发生数组拷贝导致内存溢出,抛出Fatal Error of Memory size 信息:
$db_records_in_array_format; //这是一个从表中持有1000行20列的大阵列,每一行至少为100个字节,所以总=1000*20*100=2MB
$cc = $db_records_in_array_format; //2MB more
some_function($cc); //Another 2MB ?
当导入或导出csv文件时, 常常会这么做.
不要认为上面的代码不会经常因内存限制导致脚本崩溃. 对于小的变量是没问题的, 但处理大数组的时候就不可避免.
(1).通过引用传递,
$a = get_large_array();
pass_to_function(&$a);
(2).或存储在类变量中:
class A {
function first() {
$this->a = get_large_array();
$this->pass_to_function();
}
function pass_to_function() {
//process $this->a
}
}
总之要尽快的 unset 它们, 让内存得以释放,减轻脚本负担.
4.错误日志
function insert_member(){
if (!$model->insert($data)) {
Log::record($model->getError, Log::SQL, 'insert_member');
return false;
}
}
上面是一个插入会员信息方法,插入数据失败时,会记录失败原因,有利于快速找到失败原因
5.使用php filter 验证数据
你肯定曾使用过正则表达式验证 email , ip地址等. 是的,每个人都这么使用. 现在, 我们想做不同的尝试, 称为filter.
php的filter扩展提供了简单的方式验证和检查输入.