来源:www.cncfan.com | 2006-1-11 | (有1537人读过)
引言
最近一段时间,PHP凭借其功能强大,简单易用的特点被越来越多的人们所喜爱和接受,成为目前最为流行的脚本编程语言之一。本文将结合用户在使用PHP过程中经常容易出现的问题,包括语法错误,程序运行错误以及逻辑错误等展开详细的介绍,希望能够对那些目前正在学习PHP语言的用户有所帮助。此外,本文还将会在文章的结束部分对PHP编程过程中应当注意的各种事项加以汇总,供读者参考。
PHP脚本语言所具有一个显著的特点就是能够自动生成变量实例,不要求用户对所需要使用的变量进行声明。该特点既有值得推崇之处,但是同时也为用户所编写的脚本程序埋下了隐患。从好的方面来说,用户不再需要象使用C语言那样,在程序的开头对每一个将要在程序中使用的变量进行声明;但是,现在用户必须非常小心每一个变量名称的正确拼写,否则就可能会在无意当中创建了新的变量。有些编程语言,例如PERL等,可以记录下程序中只使用过一次的变量的信息,根据用户的预先设置发出警告提示。此外,PERL还提供了一个功能十分强大的调试器。截止到4.0.2版本,PHP语言中还没有包含调试器。但是这并没有影响到PHP语言的流行和推广。PHP提供了非常广泛的功能,即使与象C语言这样成熟的编程语言相比也毫不逊色。可以说,PHP是目前使用最方便,对WEB支持功能最完善的脚本语言之一。
下面,就让我们言归正传,来看一看在PHP编程过程容易出现哪些问题,以及相应的应当采用什么样应对措施。
分号的使用正象我们平时写文章时必须要在每一句话的结尾处加上句号一样,PHP要求程序中的每一条语句都必须使用分号“;”结束。这是一条最基本的语法规则,但是同时也最容易出现问题。我们在编写程序时,很少会一行一行的检查是否漏掉了分号,但是一旦出现任何一处疏忽,解析程序就回立刻发出错误报告。有时,报告中可能会包含出现问题的语句行数。
<?
$Output="Hello World";
echo $Output
$Other="Blah";
print $SomeMoreText;
?>
上述代码的第二行“echo $Output”的结尾处我们漏掉了一个分号,如果执行该脚本将会产生如下错误提示:
Parse error: parse error, expecting `’,’’ or `’;’’ in /usr/local/apache/htdocs/test.php on line 8报告虽然指出了出现错误的原因,即漏掉了逗号“,”或分号“;”,但是却将出现问题的语句定在了第八行。因为这段代码非常简单,我们很容易就可以找到真正出现错误的地方。但是,如果程序非常复杂时,要想顺利的找出错误就有些困难了。
根据笔者以往的经验,建议采用以下方法:
如果当错误报告中指出的语句没有明显的问题时,可以检查位于该语句之前的其它指令行(不包括注释行)是否正确。如果仍然没有找到错误,可以将报告中指出的语句行注释掉(在该语句行的最前面加上“//”或“#”注释符号)或者改为用户能够确保完全没有问题的其它语句。之后,重新运行程序,如果错误提示仍然指向同一行,就表明真正有问题的语句应当位于被注释掉的语句行的前面。按照上述方法逐一检查位置靠前的每一行指令,直到错误提示信息发生改变。这时,我们就成功的挖出了真正的罪魁祸首。
变量的问题与其它编程语言要求用户显式声明变量不同,PHP语言允许用户自动使用所有变量而不必进行事先的声明。变量名称的拼写错误成为困扰PHP用户的一个大问题。
<?
function Combine ($FirstHalf, $SecondHalf) { $Combined_String=$FirstHalf.$SecondHalf; return $Combined_String; } $FirstString="WDVL - "; $SecondString="Illustrated Encyclopedia"; $Combine_Result=Combine ($FirstString, $SecondString); print $Combined_Result;
?>
当我们运行以上脚本时,将会看到由于程序没有返回任何数据而出现的错误提示。这里,我们为了更好的说明问题选择了一个非常直观的例子。在现实当中,有时问题并不会这么简单。相信大家都已经找到了出现问题的原因,那就是“print $Combined_Result;”中的变量名称“$Combined_Result”应当改为“$Combine_Result”。 事实上,脚本中任何一处出现的拼写错误都会导致同样的问题。如果用户怀疑自己的程序中有拼写错误的话,一个非常好的检查方法就是在变量的前后显示文字信息。例如:
print “The Combined Result is: |”.$Combined_Result.“|”;
按照上述方法替换输出语句的脚本重新执行之后的结果如下:
The Combined Result is: ||
其中,在两个管道符号“|”之间没有任何内容。按照这种方法,我们就可以在程序中找到出现问题的变量。
下面,我们再举一个更加复杂的例子进行说明。 现在,很多网络应用都需要对用户的身份进行验证。一个最简单的实现脚本可以如下: <? $Password=“Secret”; $Name=“admin”; function VerifyPassword ($UserPassword, $UserName){ if ($Password=$UserPassword && $Name=$UserName){ return 1; } else { return 0;}
} if (VerifyPassword (“foo1ish”,“admin”)){ print “The Password is correct”; } else { print “I’m sorry, the password is incorrect”; } ?>
虽然在上述脚本中调用VerifyPassword函数时输入的是错误的密码,但是程序运行之后仍然会产生如下结果:
The Password is correct
问题可能会出现在任何地方,下面就让我们使用排除法一一检查。首先,我们很难确定脚本最后的“if”条件语句是否正确。虽然看上去好象是没有问题,但是为了确保程序正确无误,我们不能放过任何一个环节。因此,我们将该条件语句注释掉,同时按照前面介绍的方法对VerifyPassword()函数进行输出。具体如下:
<? $Password=“Secret”; $Name=“admin”; function VerifyPassword ($UserPassword, $UserName){ if ($Password=$UserPassword && $Name=$UserName){ return 1; } else { return 0;} } print “The result of VerifyPassword() is:”; print VerifyPassword (“foo1ish”, “admin”); /*if (VerifyPassword (“foo1ish”, “admin”)){ print “The Password is correct”; } else { print “I’m sorry, the password is incorrect”; }*/ ?>
因为我们使用了错误的密码,所以结果应当为0。但是程序运行之后,我们发现实际结果如下:
The result of VerifyPassword() is: 1
这样,我们就知道问题是出现在VerifyPassword()函数的身上。检查了一遍函数之后,我们怀疑问题可能出现在“if”语句中。所以我们屏蔽到VerifyPassword()函数中的条件语句,并进行如下输出:
print “UserPassword => $UserPassword, Password => $Password,”; print “Password==UserPassword => ”.(int)($Password==$UserPassword).“<BR>”; print “UserName => $UserName, Name => $Name, ”; print “Name==UserName =>”.(int)($Name==$UserName).“<BR>”;
(说明:我们使用(int)($Password==$UserPassword)语句将比较结果转化为整数0或1)
程序修改之后的实际输出结果如下:
UserPassword => foo1ish, Password => , Password==UserPassword => 0 UserName => admin, Name => , Name==UserName => 1 I’m sorry, the password is incorrect
这里,我们可以清楚的看出Password和Name两个变量都是空值,也就难怪判断语句不起作用了。
那么为什么$Password为空值呢?我们在程序的开头部分就已经明确的对$Password变量进行了赋值,但是因为某种原其变量值无法带入到VerifyPassword()函数中。回想一下PHP语言关于变量作用域的规定,我们可以立刻找到出现问题的原因,那就是如果要想在函数中使用变量,必须将该变量声明为全局变量。知道了错误的根源之后,我们在VerifyPassword()函数的第一行加入以下语句,然后重新运行程序:
global $Password, $Name;
程序运行结果如下:
UserPassword => foo1ish, Password => Secret, Password==UserPassword => 0 UserName => admin, Name => admin, Name==UserName => 1 The Password is correct
为什么?按理说我们应当得到密码不正确的错误提示。再一次仔细检查遍程序之后,终于发现原来我们把逻辑运算符“==”误用成“=”,这样就把$UserPassword变量的值赋给了$Password变量。把最后的这两处错误改正过来之后,完成的程序如下:
<? $Password=“Secret”; $Name=“admin”; function VerifyPassword ($UserPassword, $UserName){ global $Password, $Name; if ($Password==$UserPassword && $Name==$UserName){ return 1; } else { return 0;}
} if (VerifyPassword (“foo1ish”, “admin”)){ print “The Password is correct”; } else { print “I’m sorry, the password is incorrect”; } ?>
执行程序得到如下结果:
I’m sorry, the password is incorrect.
输入正确密码重新运行时,得到以下结果:
The Password is correct
这样,我们就成功的找到并解决了问题。希望大家能够从以上的介绍中领悟到查找错误时的一些方法和思路。 关于数据库在WEB编程当中,数据库的作用已经越来越不容忽视。提到数据库,应当说PHP具有非常强大的数据库支持功能,从FileMaker到Oracle,几乎与所有的数据库系统都可以实现无缝连接。为了方便本文的讲解,我们将主要以MySQL为例进行说明。不过对于其它的数据库应用也同样适用。
使用PHP进行数据库操作一般需要包括以下语句:
<?
$Host="localhost";
$MySQL_UserName="root";
$MySQL_UserPass="password";
$MySQL_Database="db";
$Query="SELECT * FROM domain";
mysql_connect ($Host, $MySQL_UserName, $MySQL_UserPass);
mysql_select_db ($MySQL_Database);
$Result_ID=mysql_query ($Query);
while ($Result=mysql_fetch_row($Result_ID)){
print "------------------<BR>";
print "$Result[0]<BR>";
print "$Result[1]<BR>";
print "$Result[2]<BR>";
print "$Result[3]<BR>";
print "-------------------<BR>";
}?>
基本步骤包括建立与MySQL数据库的连接,选择数据库操作对象,然后执行查询语句。对于在上述过程中出现的错误的提示信息一般来说都能够较为准确和详细的描述所出现的问题。例如,“Connection failed due to a bad username”错误报告就清楚的指出由于用户名错误而导致与数据库的连接失败。
我们可以对以上所提到的这些函数的返回值加以利用,从而减少出现不必要的麻烦。例如,mysql_connect函数在连接成功时会返回一个连接ID标识,如果连接失败则发出错误提示。对此,我们可以进行如下利用:
if (!mysql_connect (’localhost’, ’root’, ’password’)){
print "Cannot connect to MySQL<BR>";
exit;
}当与数据库的连接出现问题时,我们可以输出错误提示,并终止程序的执行。从长远来看,这是一项非常好的防范措施。以此方式,我们重新编写脚本如下:
<?
$Host="localhost";
$MySQL_UserName="root";
$MySQL_UserPass="password";
$MySQL_Database="db";
$Query="SELECT * FROM domain";
if (!mysql_connect ($Host, $MySQL_UserName, $MySQL_UserPass)){
print "Cannot connect to MySQL: ".mysql_error();
exit;
}
if (!mysql_select_db ($MySQL_Database)){
print "Cannot select db<BR>";
exit;
}
if (!$Result_ID=mysql_query ($Query)){
print "Query Error: ".mysql_error();
exit;
}
while ($Result=mysql_fetch_row($Result_ID)){
print "------------------<BR>";
print "$Result[0]<BR>";
print "$Result[1]<BR>";
print "$Result[2]<BR>";
print "$Result[3]<BR>";
print "-------------------<BR>";
}?>
这样,当程序出现问题时,我们就可以立刻找到错误的根源,从而能够做到有的放矢。
接下来,我们就可以对数据库进行查询。不过,很多时候,当我们运行编写好的查询语句时,却得不到任何返回数据。到底是什么地方出错了呢?最好的解决方法是把SQL语句赋予一个变量,例如:
<?
....
$SQL="SELECT * FROM $TableName WHERE $ColumnName > $Limit";
$Result_ID=mysql_query($QUERY);
...?>
然后当出现问题时,使用“print”或“echo”命令显示该语句。注意检查$ColumnName和$Limit的拼写是否正确,是否无意当中创建了新的变量。使用输出显示的方法可以很容易的找到并解决拼写错误的问题。但是如果我们将SQL语句显示出来之后仍然没有找到明显的错误该怎么办呢?这里我们可以把输出的语句粘贴到象Mysql命令行接口这样的命令行工具中,看一看是否能够返回数据。如果还是无法解决问题,就应该查看一下所使用帐号的用户权限。
如今,我们可以使用许多免费提供的类完成绝大部分的数据库操作。PHP Classes(http://phpclasses.upperdesign.com/)上就有许多相关的信息,可以供有兴趣的用户参考。其中,MetaBase能够提供不依赖某种数据库系统的查询和管理。如果用户正在同时使用几种不同的数据库系统,或者希望自己的程序能够移植到其它的数据库平台上的话,可以留意一下MetaBase的使用。
注意事项最后,我们把使用PHP进行编程的过程中所应当注意的一些问题进行一下汇总,希望能够对大家有所帮助。
1.检查(),[],以及{}等符号,看看是否成对出现。
2.检查字符串,注意如果要想在“”当中再使用“”的话,必须使用转义符“”。
3.检查保留关键字的拼写是否正确。例如,myslq_num_rows()应当改为mysql_num_rows。
4.对照PHP用户手册(www.php.net/manual),检查程序的语法是否正确。
5.如果在函数中使用全局变量,一定不要忘了进行变量声明。
6.如果希望使用setCookie()函数设置Cookie信息,一定要确保在此之前没有输出任何字符,包括在“<?”或“<?php”之前不能有任何空格。“<?”必须作为程序的第一行。
7.如果数据库查询操作失败,使用echo或print写出查询语句,检查语法是否正确,特别应当注意语句中出现的变量。
8.如果SQL语句没有明显问题,可以尝试着使用数据库系统所提供的命令行接口。
9.如果问题仍然没有解决,应当检查是否具有足够的数据库访问权限。
10.如果出现“can’t redeclare foo()”错误,表明用户可能把同一个文件引用了两次。可以使用include_once()函数避免出现这一问题。
11.注意区分大小写。例如,$Foo和$FOO是两个不同的变量。
12.注意数组的正确使用格式。例如:$this->$foo()和$this->$variable应当分别改为$this->foo()和$this->variable。
|