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扩展提供了简单的方式验证和检查输入.