技巧:PHP+MYSQL動態網頁編程錯誤修正指南

來源:互聯網
上載者:User

關於資料庫在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_Datab ="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。

分號的使用正象我們平時寫文章時必須要在每一句話的結尾處加上句號一樣,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命令列介面這樣的命令列工具中,看一看是否能夠返回資料。如果還是無法解決問題,就應該查看一下所使用帳號的使用者權限。



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。