PHP是一门高效的网络编程语言由于它具有编写灵活运行快速等优点迅速成为Web程序员的首选语言前不久的一份权威调查表明现在已经有%的网站使用PHP作为主要的服务器端编程语言
但是要成为一名PHP编程高手却并不容易并不像很多人想象的那样只要能够飞快地编写几条简单的代码去解决一个复杂的问题就是PHP编程高手了真正的PHP高手还需要考虑更多的其它问题以下三条准则是一名成熟的PHP程序员在编程中应该首先遵循的准则
懒惰是金
编写漂亮的代码
追求程序的速度而不是编程的速度
一懒惰是金
做一个懒惰的程序员吗?这个想法太奇怪了!因为这个世界上最忙碌的人可能就是计算机程序员了但正是因为程序员太忙了所以才应该在编程时学会偷懒
对于一个程序员来说懒惰的方法有两种
其一大胆使用现成的别人的程序代码把这些代码融入到你自己的程序或者项目中去
其二是编写一些有用的代码建立一个函数库在将来编写程序时可以顺手拈来省去了许多重复的劳动自然就可以懒惰一点了
这两种偷懒的方法都非常适合PHP程序员了
首先PHP是在自由开放的环境中诞生和成长的一门语言在世界各地有成千上万的程序员他们一直在为PHP的完美而不断奋斗他们也愿意和别人分享自己的聪明才智和自己编写的代码你每天都可以从一些PHP网站邮件列表新闻组发现大量的优秀的程序代码这样说我并不是鼓励你整天等着让别人为你编写代码但是你可以站在伟人的肩膀上充分发扬拿来主义聪明地应用别人的程序代码可以节省你大量时间其次在PHP中你可以方便地建立自己的函数库这样可以在你以后编写程序时省去很多麻烦
下面笔者为大家介绍几个通用的函数这些函数有的来自网上的一些开放源代码的项目有的精选自邮件列表如果你能把它们加入到你自己的函数库中迟早你将会发现自己受益无穷
通用数据库处理函数
和其它的CGI函数相比PHP的优点之一是具有很强大的数据库处理能力但是在PHP中对于不同的数据库都使用一些特定的函数来专门处理缺少通用的数据库处理函数这大大降低了程序代码的可移植性这也为初学编程的朋友带来了很多不便
在网上许多程序员都通过封装类解决了这个问题他们编写了统一的函数用来处理任何流行的数据库——不管是在Linux世界深受欢迎的Mysql还是在Windows平台上广泛流行的SqlServer就笔者个人来说非常喜欢使用这些函数因为可以直接使用一些简单的诸如querynext_record之类的函数而不需要考虑数据库的连接数据库句柄这些复杂的东西更不需要考虑使用的是何种数据库
如果你需要这些函数你可以通过访问以下的几个网址而得到
_blank>http://phplibnetusede/
_blank>http://phpclassesUpperDesigncom/browsehtml/package/
linuxboxcom/ target=_blank>http://phpdblinuxboxcom/
变量调试函数
PHP程序的调试一直是一件让人头疼的事它既不像VB等高级语言那样有集成的编译调试环境也不想Perl那样可以在Linux或者DOS环境下直接运行其实我们完全可以通过灵活地使用echo语句来完成对PHP的调试工作
下面的几个函数可以让你随时查看程序中任何变量的类型及其值
function ss_array_as_string (&$array $column = )
{
$str = Array( n; while(list($var $val) = each($array))
{
for ($i = ; $i < $column+; $i++)
{
$str = &nbsp;&nbsp;&nbsp;&nbsp;;
}
$str = $var ==> ;
$str = ss_as_string($val $column+)
n;
}
for ($i = ; $i < $column; $i++)
{
$str = &nbsp;&nbsp;&nbsp;&nbsp;;
}
return $str);
}
function ss_object_as_string (&$object $column = )
{
if (empty($object->classname))
{
return $object;
}
else
{
$str = $object->classname( n; while (list($var) = each($object->persistent_slots))
{
for ($i = ; $i < $column; $i++)
{
$str = &nbsp;&nbsp;&nbsp;&nbsp;;
}
global $$var;
$str = $var ==> ;
$str = ss_as_string($$var column+)
n;
}
for ($i = ; $i < $column; $i++)
{
$str = &nbsp;&nbsp;&nbsp;&nbsp;;
}
return $str);
}
}
function ss_as_string (&$thing $column = )
{
if (is_object($thing))
{
return ss_object_as_string($thing $column);
}
elseif (is_array($thing))
{
return ss_array_as_string($thing $column);
}
elseif (is_double($thing))
{
return Double($thing);
}
elseif (is_long($thing))
{
return Long($thing);
}
elseif (is_string($thing))
{
return String($thing);
}
else
{
return Unknown($thing);
}
}
需要的时候在程序中简单地加入下面的一条代码即可查看程序中的所使用的变量(包括数组和对象)的类型和值
echo ss_as_string($my_variable);
使用下面的语句我们可以直接查看程序中所有的变量的值
echo ss_as_string($GLOBALS);
控制Log信息的函数
调试PHP程序的另外一种重要的方法就是查看Log信息如果能够方便地控制Log信息的级别以及Log信息的显示内容将会给程序调试带来更多的便利下面的几个函数可以方便地实现这个功能
$ss_log_level = ;
$ss_log_filename = /tmp/ss-log;
$ss_log_levels = array(
NONE =>
ERROR =>
INFO =>
DEBUG => );
function ss_log_set_level ($level = ERROR)
{
global $ss_log_level;
$ss_log_level = $level;
}
function ss_log ($level $message)
{
global $ss_log_level $ss-log-filename;
if ($ss_log_levels[$ss_log_level] < $ss_log_levels[$level])
{
// 不显示Log信息
return false;
}
$fd = fopen($ss_log_filename a+);
fputs($fd $level - [ss_timestamp_pretty()] - $messagen);
fclose($fd);
return true;
}
function ss_log_reset ()
{
global $ss_log_filename;
@unlink($ss_log_filename);
}
在上面的函数中有四个Log级别变量运行PHP程序时只有当Log的级别低于预设的级别值时Log信息才可以被记录和显示出来例如在程序中加入如下的一条语句
ss_log_set_level(INFO);
那么运行PHP程序时只有ERROR和INFO级别的LOG信息才能被记录和显示出来DEBUG级的信息则被忽略了除此之外我们还可以设定显示的信息内容其语句如下
ss_log(ERROR testing level ERROR);
ss_log(INFO testing level INFO);
ss_log(DEBUG testing level DEBUG);
你也可以随时使用下面的语句清空LOG信息
ss_log_reset();
速度测试函数
为了优化代码我们需要一种可以测试代码运行时间的方法从而来选择最优的代码下面的函数可以测试运行代码所需的时间
function ss_timing_start ($name = default)
{
global $ss_timing_start_times;
$ss_timing_start_times[$name] = explode( microtime());
}
function ss_timing_stop ($name = default)
{
global $ss_timing_stop_times;
$ss_timing_stop_times[$name] = explode( microtime());
}
function ss_timing_current ($name = default)
{
global $ss_timing_start_times $ss_timing_stop_times;
if (!isset($ss_timing_start_times[$name]))
{
return ;
}
if (!isset($ss_timing_stop_times[$name]))
{
$stop_time = explode( microtime());
}
else
{
$stop_time = $ss_timing_stop_times[$name];
}
$current = $stop_time[] - $ss_timing_start_times[$name][];
$current += $stop_time[] - $ss_timing_start_times[$name][];
return $current;
}
现在可以轻松地检查任何一段代码的执行时间了甚至我们可以同时使用多个计时器只需在使用上述的几个函数时设定不同的参数作为计时器的名称就可以了
调试和优化数据库的操作
对于数据库来说运行速度是至关重要的尽管很多书籍和文章都讲授了一些快速运行数据库的方法但是所有的方法都必须经过实践的检验下面我们将把PHPLib函数库中的query()函数和上面介绍的几个函数综合起来编写成新的query()函数和原先的函数相比这个函数增加了运行时间的监测功能
function query($Query_String $halt_on_error = )
{
$this->connect();
ss_timing_start();
$this->Query_ID = @mysql_query($Query_String$this->Link_ID);
ss_timing_stop();
ss_log(INFO ss_timing_current() Secs - $Query_String);
$this->Row = ;
$this->Errno = mysql_errno();
$this->Error = mysql_error();
if ($halt_on_error && !$this->Query_ID)
{
$this->halt(Invalid SQL: $Query_String);
}
return $this->Query_ID;
}
二编写漂亮的代码
将后台程序与前端程序分开
在编写PHP程序时有些代码是用来处理一些事务例如操作数据库进行数学运算等而另外的一些代码则只是事务处理的结果显示出来例如一些使用echo语句将结果以HTML的格式显示在Web浏览器上的PHP代码以及那些直接嵌入PHP程序的HTML代码首先我们应该清晰地区分这两种代码把前者称为后台程序把后者称为前端程序
因为PHP是一种嵌入式编程语言也就是说所有的PHP代码都可以嵌入到HTML代码之中这为程序的编写带来了许多便利之处但是物极必反如果在一段较长的程序中将PHP代码和HTML代码混合编写这将使程序杂乱无章不利于程序的维护和阅读所以我们需要尽可能地将这些程序中混杂于HTML代码中的PHP代码移植出来在专门的文件中将这些代码封装成函数然后在HTML代码中使用include语句来包含这些文件在适当的位置调用这些函数即可
这种做法一方面使HTML代码和PHP代码都简单易读另一方面因为HTML代码需要不断更新而这种分离的方法可以确保后台程序不会被破坏
同前端程序不同后台程序更多追求的是稳定结构化极少更改所以应该认真地设计和管理其实在设计台程序时投入大量时间是值得的现在栽树以后乘凉在以后的设计工作中将可以轻松地使用现在编写的后台程序
灵活使用包含文件
正如前面所说的那样后台程序应当安排在一系列的包含文件中包含文件可以通过include语句在需要时动态装入也可以在phpini文件中通过使用auto_prepend_file指令预先自动装入
如果使用后一种方法的话虽然取得了一劳永逸的好处但是也有一些缺点值得我们注意下面的一段代码向我们展示了解析一个庞大的包含文件需要一定的时间
require(timinginc);
ss_timing_start();
include(testinc);
ss_timing_stop();
echo
ss_timing_current()
;
?>
在上面的代码中testinc是一个行的包含文件运行的结果显示解析这个包含文件花费了秒钟对于一个大型网站来说这个速度并不是可以忽略不记的
使用包含文件的另外一个缺点是如果一个文件中的一个语句发生错误将会使整个网站的PHP程序都无法运行所以使用起来也及其小心
其实对包含文件稍做处理即可以使包含文件只在需要时进行解析下面的代码使abcinc文件只在程序需要时才作解析
if ( defined( __LIBA_INC) ) return;
define( __LIBA_INC );
/*
* 代码
*/
?>
使用面向对象的编程方法
PHP也是一种面向对象的语言面向对象的编程方法是优秀的程序员们非常推崇的一种软件设计方法在PHP编程中可以充分发挥面向对象语言的优势对编程中的对象进行封装在前面的代码中我们使用了面向对象的方法例如在管理数据库时我们将query()函数封装进数据库类中这极大地方便了代码的管理增加了程序的可读性
三追求程序速度而不是编程的速度
在网站建设中程序运行速度和网页下载速度都是关系成败的重要因素作为一名Web程序员应该更加注意代码的运行速度下面介绍的几种方法都在不同程度上提高了代码的运行速度
使用内嵌的HTML代码而不是PHP的echo语句
因为PHP是一门嵌入式Web编程语言可以将HTML代码和PHP代码相互嵌入但是很多程序员担心在HTML代码中过多的使用嵌入PHP代码会多次调用PHP解释器从而降低了PHP代码的运行速度所以宁愿使用PHP的echo语句来输出HTML代码而不直接使用HTML代码但事实却恰恰相反每一个PHP页面只调用一次PHP解释器来解释所有的PHP代码所以只在需要时才嵌入PHP代码而大多数的时候直接使用HTML代码输入结果不但不会降低程序的运行速度而且因为减少了对echo语句的解析往往可以提高代码的运行速度
下面的一段代码证明了我们的结论在这段代码中我们使用了前面介绍的时间测试函数
使用str-replace而不是ereg-replace 习惯使用Perl进行编程的程序员更加愿意使用ereg_replace完成字符串替换工作因为在PHP中ereg_replace的用法和Perl中模式匹配的用法相近但是下面的这段代码证明使用str_replace 代替 ereg_replace将可以大大提高代码的运行速度
测试str_replace和ereg_replace的运行速度
//这段代码测试str_replace的运行速度
emphasis; ?>
for ($i=; $i<; $i++)
{
str_replace(i> b> $string)
;
}
?>
//这段代码测试ereg_replace的运行速度
for ($i=; $i<; $i++)
{
ereg_replace(<([/]*)i> <b> $string);
}
?>
//打印结果
结论
使用str_replace的时间 -
使用ereg_pattern的时间 -
运行上面的代码得到的结果是
使用str_replace的时间 -
使用ereg_pattern的时间 -
从运行的结果我们可以看出使用str_replace替代ereg_replace作为字符串替换函数极大地提高了代码的运行速度
注意字符串的引用
PHP和其它很多编程语言一样可以使用双引号()来引用字符串也可以使用单引号()但是在PHP中如果使用双引号来引用字符串那么PHP解析器将首先分析字符串中有没有对变量的引用有变量的话将对变量进行替换如果是单引号则没有如此复杂——直接将单引号包含起来的所有字符串直接显示出来显然在PHP编程中如果使用单引号引用字符串变量要比使用双引号快速一些
在数据库中避免使用联合操作
比起其它的Web编程语言来说PHP的数据库功能十分强大但是在PHP中数据库的运行仍然是一件十分费时费力的事情所以作为一个Web程序员要尽量减少数据库的查询操作同时应该为数据库建立适当的索引另一件值得注意的事情是在用PHP操作数据库时尽可能不使用多个数据表的联合操作尽管联合操作可以增强数据库的查询功能但是却大大增加了服务器的负担
为了说明这个问题我们可以看看下面的这个简单的例子
我们在数据库中创建了两个数据表foo和big_foo在数据表foo中只有一个字段包含了从-之间的所有自然数数据表big_foo同样只有一个字段但包含了从-之间的全部自然数所以从大小上说big_foo等于foo与它自身进行了联合操作
$db->query(select * from foo);
secs
$db->next_record();
secs
$db->query(insert into foo values (NULL));
secs
$db->query(select * from foo as a foo as b);
secs
$db->query(select * from foo as a foo as b where aid > bid);
secs
$db->query(select * from foo as a foo as b where aid = bid);
secs
$db->query(select * from big_foo);
secs
从上面操作结果我们可以发现对于两个有条记录的数据表进行联合其速度并不比对一个条纪录的大型数据表单独进行操作快多少
注意include与require的区别
在PHP变成中include()与require()的功能相同但在用法上却有一些不同include()是有条件包含函数而require()则是无条件包含函数例如在下面的一个例子中如果变量$somgthing为真则将包含文件somefile
if($something)
{
include(somefile);
}
但不管$something取何值下面的代码将把文件somefile包含进文件里
if($something)
{
require(somefile);
}
下面的这个有趣的例子充分说明了这两个函数之间的不同
$i = ;
while ($i < )
{
require(somefile$i);
$i++;
}
在这段代码中每一次循环的时候程序都将把同一个文件包含进去很显然这不是程序员的初衷从代码中我们可以看出这段代码希望在每次循环时将不同的文件包含进来如果要完成这个功能必须求助函数include()
$i = ;
while ($i < )
{
include(somefile$i);
$i++;
}
注意echo和print的区别
PHP中echo和print的功能也基本相同但是两者之间也有细微差别在PHP代码中可以把print作为一个普通函数来使用例如执行下面的代码后变量$res的值将为
$ret = print Hello World;
这意味着print可用在一些复杂的表达式中而echo则不行同样在代码中echo语句的运行速度要略微快于print语句因为echo语句不要求返回任何数值