cookie 常用于識別用戶。
8.1 什么是 Cookie?cookie 常用于識別用戶。cookie 是服務(wù)器留在用戶計算機中的小文件。每當(dāng)相同的計算機通過瀏覽器請求頁面時,它同時會發(fā)送 cookie。通過 PHP,您能夠創(chuàng)建并取回 cookie 的值。
8.2 如何創(chuàng)建 cookie?setcookie() 函數(shù)用于設(shè)置 cookie。
注釋:setcookie() 函數(shù)必須位于 <html> 標簽之前。
語法setcookie(name, value, expire, path, domain);例子
在下面的例子中,我們將創(chuàng)建名為 "user" 的 cookie,把為它賦值 "Alex Porter"。我們也規(guī)定了此 cookie 在一小時后過期:
<?php setcookie("user", "Alex Porter", time()+3600);?><html><body></body></html>
注釋:在發(fā)送 cookie 時,cookie 的值會自動進行 URL 編碼,在取回時進行自動解碼(為防止 URL 編碼,請使用 setrawcookie() 取而代之)。
8.3 如何取回 Cookie 的值?PHP 的 $_COOKIE 變量用于取回 cookie 的值。
在下面的例子中,我們?nèi)』亓嗣麨?"user" 的 cookie 的值,并把它顯示在了頁面上:
<?php// Print a cookieecho $_COOKIE["user"];// A way to view all cookiesprint_r($_COOKIE);?>
在下面的例子中,我們使用 isset() 函數(shù)來確認是否已設(shè)置了 cookie:
<html><body><?phpif (isset($_COOKIE["user"])) echo "Welcome " . $_COOKIE["user"] . "!<br />";else echo "Welcome guest!<br />";?></body></html>8.4 如何刪除 cookie?
當(dāng)刪除 cookie 時,您應(yīng)當(dāng)使過期日期變更為過去的時間點。
刪除的例子:
<?php // set the expiration date to one hour agosetcookie("user", "", time()-3600);?>8.5 如果瀏覽器不支持 cookie 該怎么辦?
如果應(yīng)用程序涉及不支持 cookie 的瀏覽器,應(yīng)采取其他方法在應(yīng)用程序中從一張頁面向另一張頁面?zhèn)鬟f信息。一種方式是從表單傳遞數(shù)據(jù)(有關(guān)表單和用戶輸入的內(nèi)容,在前面已介紹過了)。
下面的表單在用戶單擊提交按鈕時向 "welcome.php" 提交了用戶輸入:
<html><body><form action="welcome.php" method="post">Name: <input type="text" name="name" />Age: <input type="text" name="age" /><input type="submit" /></form></body></html>
取回 "welcome.php" 中的值,就像這樣:
<html><body>Welcome <?php echo $_POST["name"]; ?>.<br />You are <?php echo $_POST["age"]; ?> years old.</body></html>9、PHP Sessions
PHP session 變量用于存儲有關(guān)用戶會話的信息,或更改用戶會話的設(shè)置。Session 變量保存的信息是單一用戶的,并且可供應(yīng)用程序中的所有頁面使用。
9.1 PHP Session 變量當(dāng)運行一個應(yīng)用程序時,會打開它,做些更改,然后關(guān)閉它。這很像一次會話。計算機清楚你是誰。它知道你何時啟動應(yīng)用程序,并在何時終止。但是在因特網(wǎng)上,存在一個問題:服務(wù)器不知道你是誰以及你做什么,這是由于 HTTP 地址不能維持狀態(tài)。
通過在服務(wù)器上存儲用戶信息以便隨后使用,PHP session 解決了這個問題(比如用戶名稱、購買商品等)。不過,會話信息是臨時的,在用戶離開網(wǎng)站后將被刪除。如果需要永久儲存信息,可以把數(shù)據(jù)存儲在數(shù)據(jù)庫中。
Session 的工作機制是:為每個訪問者創(chuàng)建一個唯一的 id (UID),并基于這個 UID 來存儲變量。UID 存儲在 cookie 中,亦或通過 URL 進行傳導(dǎo)。
9.2 開始 PHP Session在把用戶信息存儲到 PHP session 中之前,首先必須啟動會話。
注釋:session_start() 函數(shù)必須位于 <html> 標簽之前:
<?php session_start(); ?><html><body></body></html>
上面的代碼會向服務(wù)器注冊用戶的會話,以便您可以開始保存用戶信息,同時會為用戶會話分配一個 UID。
9.3 存儲 Session 變量存儲和取回 session 變量的正確方法是使用 PHP $_SESSION 變量:
<?phpsession_start();// store session data$_SESSION['views']=1;?><html><body><?php//retrieve session dataecho "Pageviews=". $_SESSION['views'];?></body></html>
輸出:
Pageviews=1
在下面的例子中,我們創(chuàng)建了一個簡單的 page-view 計數(shù)器。isset() 函數(shù)檢測是否已設(shè)置 "views" 變量。如果已設(shè)置 "views" 變量,我們累加計數(shù)器。如果 "views" 不存在,則我們創(chuàng)建 "views" 變量,并把它設(shè)置為 1:
<?phpsession_start();if(isset($_SESSION['views'])) $_SESSION['views']=$_SESSION['views']+1;else $_SESSION['views']=1;echo "Views=". $_SESSION['views'];?>9.4 終結(jié) Session
如果希望刪除某些 session 數(shù)據(jù),可以使用 unset() 或 session_destroy() 函數(shù)。
unset() 函數(shù)用于釋放指定的 session 變量:
<?phpunset($_SESSION['views']);?>
您也可以通過 session_destroy() 函數(shù)徹底終結(jié) session:
<?phpsession_destroy();?>
注釋:session_destroy() 將重置 session,您將失去所有已存儲的 session 數(shù)據(jù)。
10、PHP 發(fā)送電子郵件PHP 允許您從腳本直接發(fā)送電子郵件。
10.1 PHP mail() 函數(shù)PHP mail() 函數(shù)用于從腳本中發(fā)送電子郵件。
語法mail(to,subject,message,headers,parameters)
注釋:PHP 需要一個已安裝且正在運行的郵件系統(tǒng),以便使郵件函數(shù)可用。所用的程序通過在 php.ini 文件中的配置設(shè)置進行定義。
10.2 PHP 簡易 E-Mail通過 PHP 發(fā)送電子郵件的最簡單的方式是發(fā)送一封文本 email。
在下面的例子中,我們首先聲明變量($to, $subject, $message, $from, $headers),然后我們在 mail() 函數(shù)中使用這些變量來發(fā)送了一封 e-mail:
<?php$to = "someone@example.com";$subject = "Test mail";$message = "Hello! This is a simple email message.";$from = "someonelse@example.com";$headers = "From: $from";mail($to,$subject,$message,$headers);echo "Mail Sent.";?>10.3 PHP Mail Form
通過 PHP,能夠在自己的站點制作一個反饋表單。下面的例子向指定的 e-mail 地址發(fā)送了一條文本消息:
<html><body><?phpif (isset($_REQUEST['email']))//if "email" is filled out, send email { //send email $email = $_REQUEST['email'] ; $subject = $_REQUEST['subject'] ; $message = $_REQUEST['message'] ; mail( "someone@example.com", "Subject: $subject", $message, "From: $email" ); echo "Thank you for using our mail form"; }else//if "email" is not filled out, display the form { echo "<form method='post' action='mailform.php'> Email: <input name='email' type='text' /><br /> Subject: <input name='subject' type='text' /><br /> Message:<br /> <textarea name='message' rows='15' cols='40'> </textarea><br /> <input type='submit' /> </form>"; }?></body></html>例子解釋:首先,檢查是否填寫了郵件輸入框如果未填寫(比如在頁面被首次訪問時),輸出 HTML 表單如果已填寫(在表單被填寫后),從表單發(fā)送郵件當(dāng)點擊提交按鈕后,重新載入頁面,顯示郵件發(fā)送成功的消息11、PHP 安全的電子郵件
在前面的 PHP e-mail 腳本中,存在著一個漏洞。
11.1 PHP E-mail 注入首先,請看前面的 PHP 代碼:
<html><body><?phpif (isset($_REQUEST['email']))//if "email" is filled out, send email { //send email $email = $_REQUEST['email'] ; $subject = $_REQUEST['subject'] ; $message = $_REQUEST['message'] ; mail("someone@example.com", "Subject: $subject", $message, "From: $email" ); echo "Thank you for using our mail form"; }else//if "email" is not filled out, display the form { echo "<form method='post' action='mailform.php'> Email: <input name='email' type='text' /><br /> Subject: <input name='subject' type='text' /><br /> Message:<br /> <textarea name='message' rows='15' cols='40'> </textarea><br /> <input type='submit' /> </form>"; }?></body></html>
以上代碼存在的問題是,未經(jīng)授權(quán)的用戶可通過輸入表單在郵件頭部插入數(shù)據(jù)。
假如用戶在表單中的輸入框內(nèi)加入這些文本,會出現(xiàn)什么情況呢?
someone@example.com%0ACc:person2@example.com%0ABcc:person3@example.com,person3@example.com,anotherperson4@example.com,person5@example.com%0ABTo:person6@example.com
與往常一樣,mail() 函數(shù)把上面的文本放入郵件頭部,那么現(xiàn)在頭部有了額外的 Cc:, Bcc: 以及 To: 字段。當(dāng)用戶點擊提交按鈕時,這封 e-mail 會被發(fā)送到上面所有的地址!
11.2 PHP 防止 E-mail 注入防止 e-mail 注入的最好方法是對輸入進行驗證。
下面的代碼增加了檢測表單中 email 字段的輸入驗證程序:
<html><body><?phpfunction spamcheck($field) { //filter_var() sanitizes the e-mail //address using FILTER_SANITIZE_EMAIL $field=filter_var($field, FILTER_SANITIZE_EMAIL); //filter_var() validates the e-mail //address using FILTER_VALIDATE_EMAIL if(filter_var($field, FILTER_VALIDATE_EMAIL)) { return TRUE; } else { return FALSE; } }if (isset($_REQUEST['email'])) {//if "email" is filled out, proceed //check if the email address is invalid $mailcheck = spamcheck($_REQUEST['email']); if ($mailcheck==FALSE) { echo "Invalid input"; } else {//send email $email = $_REQUEST['email'] ; $subject = $_REQUEST['subject'] ; $message = $_REQUEST['message'] ; mail("someone@example.com", "Subject: $subject", $message, "From: $email" ); echo "Thank you for using our mail form"; } }else {//if "email" is not filled out, display the form echo "<form method='post' action='mailform.php'> Email: <input name='email' type='text' /><br /> Subject: <input name='subject' type='text' /><br /> Message:<br /> <textarea name='message' rows='15' cols='40'> </textarea><br /> <input type='submit' /> </form>"; }?></body></html>
在上面的代碼中,我們使用了 PHP 過濾器來對輸入進行驗證:
FILTER_SANITIZE_EMAIL 從字符串中刪除電子郵件的非法字符FILTER_VALIDATE_EMAIL 驗證電子郵件地址12、PHP 錯誤處理在 PHP 中,默認的錯誤處理很簡單。一條消息會被發(fā)送到瀏覽器,這條消息帶有文件名、行號以及一條描述錯誤的消息。
12.1 PHP 錯誤處理在創(chuàng)建腳本和 web 應(yīng)用程序時,錯誤處理是一個重要的部分。如果代碼缺少錯誤檢測編碼,那么程序看上去很不專業(yè),也為安全風(fēng)險敞開了大門。
下面介紹 PHP 中一些最為重要的錯誤檢測方法。
介紹不同的錯誤處理方法:
簡單的 "die()" 語句 自定義錯誤和錯誤觸發(fā)器錯誤報告12.2 基本的錯誤處理:使用 die() 函數(shù)第一個例子展示了一個打開文本文件的簡單腳本:
<?php$file=fopen("welcome.txt","r");?>
如果文件不存在,會獲得類似這樣的錯誤:
Warning: fopen(welcome.txt) [function.fopen]: failed to open stream: No such file or directory in C:webfolder est.php on line 2
為了避免用戶獲得類似上面的錯誤消息,在訪問文件之前檢測該文件是否存在:
<?phpif(!file_exists("welcome.txt")) { die("File not found"); }else { $file=fopen("welcome.txt","r"); }?>
現(xiàn)在,假如文件不存在,會得到類似這樣的錯誤消息:
File not found
比起之前的代碼,上面的代碼更有效,這是由于它采用了一個簡單的錯誤處理機制在錯誤之后終止了腳本。
不過,簡單地終止腳本并不總是恰當(dāng)?shù)姆绞健?/p>12.3 創(chuàng)建自定義錯誤處理器
創(chuàng)建一個自定義的錯誤處理器非常簡單。簡單地創(chuàng)建了一個專用函數(shù),可以在 PHP 中發(fā)生錯誤時調(diào)用該函數(shù)。
該函數(shù)必須有能力處理至少兩個參數(shù) (error level 和 error message),但是可以接受最多五個參數(shù)(可選的:file, line-number 以及 error context):
語法error_function(error_level,error_message,error_file,error_line,error_context)
這些錯誤報告級別是錯誤處理程序旨在處理的錯誤的不同的類型:
現(xiàn)在,讓我們創(chuàng)建一個處理錯誤的函數(shù):
function customError($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr<br />"; echo "Ending Script"; die(); }
上面的代碼是一個簡單的錯誤處理函數(shù)。當(dāng)它被觸發(fā)時,它會取得錯誤級別和錯誤消息。然后它會輸出錯誤級別和消息,并終止腳本。
現(xiàn)在,我們已經(jīng)創(chuàng)建了一個錯誤處理函數(shù),我們需要確定在何時觸發(fā)該函數(shù)。
12.5 Set Error HandlerPHP 的默認錯誤處理程序是內(nèi)建的錯誤處理程序。想把上面的函數(shù)改造為腳本運行期間的默認錯誤處理程序。
可以修改錯誤處理程序,使其僅應(yīng)用到某些錯誤,這樣腳本就可以不同的方式來處理不同的錯誤。不過,在本例中,針對所有錯誤來使用我們的自定義錯誤處理程序:
set_error_handler("customError");
由于希望自定義函數(shù)來處理所有錯誤,set_error_handler() 僅需要一個參數(shù),可以添加第二個參數(shù)來規(guī)定錯誤級別。
實例通過嘗試輸出不存在的變量,來測試這個錯誤處理程序:
<?php//error handler functionfunction customError($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr"; }//set error handlerset_error_handler("customError");//trigger errorecho($test);?>
以上代碼的輸出應(yīng)該類似這樣:
Error: [8] Undefined variable: test12.6 觸發(fā)錯誤
在腳本中用戶輸入數(shù)據(jù)的位置,當(dāng)用戶的輸入無效時觸發(fā)錯誤的很有用的。在 PHP 中,這個任務(wù)由 trigger_error() 完成。
例子在本例中,如果 "test" 變量大于 "1",就會發(fā)生錯誤:
<?php$test=2;if ($test>1){trigger_error("Value must be 1 or below");}?>
以上代碼的輸出應(yīng)該類似這樣:
Notice: Value must be 1 or belowin C:webfolder est.php on line 6
可以在腳本中任何位置觸發(fā)錯誤,通過添加的第二個參數(shù),能夠規(guī)定所觸發(fā)的錯誤級別。
可能的錯誤類型:E_USER_ERROR - 致命的用戶生成的 run-time 錯誤。錯誤無法恢復(fù)。腳本執(zhí)行被中斷。E_USER_WARNING - 非致命的用戶生成的 run-time 警告。腳本執(zhí)行不被中斷。E_USER_NOTICE - 默認。用戶生成的 run-time 通知。腳本發(fā)現(xiàn)了可能的錯誤,也有可能在腳本運行正常時發(fā)生。例子在本例中,如果 "test" 變量大于 "1",則發(fā)生 E_USER_WARNING 錯誤。如果發(fā)生了 E_USER_WARNING,將使用自定義錯誤處理程序并結(jié)束腳本:
<?php//error handler functionfunction customError($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr<br />"; echo "Ending Script"; die(); }//set error handlerset_error_handler("customError",E_USER_WARNING);//trigger error$test=2;if ($test>1) { trigger_error("Value must be 1 or below",E_USER_WARNING); }?>
以上代碼的輸出應(yīng)該類似這樣:
Error: [512] Value must be 1 or belowEnding Script
現(xiàn)在,已經(jīng)介紹了如何創(chuàng)建自己的 error,以及如何觸發(fā)它們,現(xiàn)在介紹一下錯誤記錄。
12.7 錯誤記錄默認地,根據(jù)在 php.ini 中的 error_log 配置,PHP 向服務(wù)器的錯誤記錄系統(tǒng)或文件發(fā)送錯誤記錄。通過使用 error_log() 函數(shù),可以向指定的文件或遠程目的地發(fā)送錯誤記錄。
通過電子郵件向自己發(fā)送錯誤消息,是一種獲得指定錯誤的通知的好辦法。
通過 E-Mail 發(fā)送錯誤消息在下面的例子中,如果特定的錯誤發(fā)生,將發(fā)送帶有錯誤消息的電子郵件,并結(jié)束腳本:
<?php//error handler functionfunction customError($errno, $errstr) { echo "<b>Error:</b> [$errno] $errstr<br />"; echo "Webmaster has been notified"; error_log("Error: [$errno] $errstr",1, "someone@example.com","From: webmaster@example.com");}//set error handlerset_error_handler("customError",E_USER_WARNING);//trigger error$test=2;if ($test>1) { trigger_error("Value must be 1 or below",E_USER_WARNING); }?>
以上代碼的輸出應(yīng)該類似這樣:
Error: [512] Value must be 1 or belowWebmaster has been notified
接收自以上代碼的郵件類似這樣:
Error: [512] Value must be 1 or below
這個方法不適合所有的錯誤。常規(guī)錯誤應(yīng)當(dāng)通過使用默認的 PHP 記錄系統(tǒng)在服務(wù)器上進行記錄。
13、PHP 異常處理異常(Exception)用于在指定的錯誤發(fā)生時改變腳本的正常流程。
13.1 什么是異常?PHP 5 提供了一種新的面向?qū)ο?/u>的錯誤處理方法。
異常處理用于在指定的錯誤(異常)情況發(fā)生時改變腳本的正常流程。這種情況稱為異常。
當(dāng)異常被觸發(fā)時,通常會發(fā)生:
當(dāng)前代碼狀態(tài)被保存代碼執(zhí)行被切換到預(yù)定義的異常處理器函數(shù)根據(jù)情況,處理器也許會從保存的代碼狀態(tài)重新開始執(zhí)行代碼,終止腳本執(zhí)行,或從代碼中另外的位置繼續(xù)執(zhí)行腳本我們將介紹不同的錯誤處理方法:
異常的基本使用創(chuàng)建自定義的異常處理器多個異常重新拋出異常設(shè)置頂層異常處理器13.2 異常的基本使用當(dāng)異常被拋出時,其后的代碼不會繼續(xù)執(zhí)行,PHP 會嘗試查找匹配的 "catch" 代碼塊。
如果異常沒有被捕獲,而且又沒用使用 set_exception_handler() 作相應(yīng)的處理的話,那么將發(fā)生一個嚴重的錯誤(致命錯誤),并且輸出 "Uncaught Exception" (未捕獲異常)的錯誤消息。
嘗試拋出一個異常,同時不去捕獲它:
<?php//create function with an exceptionfunction checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; }//trigger exceptioncheckNum(2);?>
上面的代碼會獲得類似這樣的一個錯誤:
Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in C:webfolder est.php:6 Stack trace: #0 C:webfolder est.php(12): checkNum(28) #1 {main} thrown in C:webfolder est.php on line 613.3 Try, throw 和 catch
要避免上面例子出現(xiàn)的錯誤,我們需要創(chuàng)建適當(dāng)?shù)拇a來處理異常。
正確的處理程序應(yīng)當(dāng)包括:
Try - 使用異常的函數(shù)應(yīng)該位于 "try" 代碼塊內(nèi)。如果沒有觸發(fā)異常,則代碼將照常繼續(xù)執(zhí)行。但是如果異常被觸發(fā),會拋出一個異常。Throw - 這里規(guī)定如何觸發(fā)異常。每一個 "throw" 必須對應(yīng)至少一個 "catch"Catch - "catch" 代碼塊會捕獲異常,并創(chuàng)建一個包含異常信息的對象讓我們觸發(fā)一個異常:
<?php//創(chuàng)建可拋出一個異常的函數(shù)function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; }//在 "try" 代碼塊中觸發(fā)異常try { checkNum(2); //If the exception is thrown, this text will not be shown echo 'If you see this, the number is 1 or below'; }//捕獲異常catch(Exception $e) { echo 'Message: ' .$e->getMessage(); }?>
上面代碼將獲得類似這樣一個錯誤:
Message: Value must be 1 or below例子解釋:
上面的代碼拋出了一個異常,并捕獲了它:
創(chuàng)建 checkNum() 函數(shù)。它檢測數(shù)字是否大于 1。如果是,則拋出一個異常。在 "try" 代碼塊中調(diào)用 checkNum() 函數(shù)。checkNum() 函數(shù)中的異常被拋出"catch" 代碼塊接收到該異常,并創(chuàng)建一個包含異常信息的對象 ($e)。通過從這個 exception 對象調(diào)用 $e->getMessage(),輸出來自該異常的錯誤消息不過,為了遵循“每個 throw 必須對應(yīng)一個 catch”的原則,可以設(shè)置一個頂層的異常處理器來處理漏掉的錯誤。
13.4 創(chuàng)建一個自定義的 Exception 類創(chuàng)建自定義的異常處理程序非常簡單。簡單地創(chuàng)建了一個專門的類,當(dāng) PHP 中發(fā)生異常時,可調(diào)用其函數(shù)。該類必須是 exception 類的一個擴展。
這個自定義的 exception 類繼承了 PHP 的 exception 類的所有屬性,您可向其添加自定義的函數(shù)。
開始創(chuàng)建 exception 類:
<?phpclass customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } }$email = "someone@example...com";try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } }catch (customException $e) { //display custom message echo $e->errorMessage(); }?>
這個新的類是舊的 exception 類的副本,外加 errorMessage() 函數(shù)。正因為它是舊類的副本,因此它從舊類繼承了屬性和方法,可以使用 exception 類的方法,比如 getLine() 、 getFile() 以及 getMessage()。
例子解釋:上面的代碼拋出了一個異常,并通過一個自定義的 exception 類來捕獲它:
customException() 類是作為舊的 exception 類的一個擴展來創(chuàng)建的。這樣它就繼承了舊類的所有屬性和方法。創(chuàng)建 errorMessage() 函數(shù)。如果 e-mail 地址不合法,則該函數(shù)返回一條錯誤消息把 $email 變量設(shè)置為不合法的 e-mail 地址字符串執(zhí)行 "try" 代碼塊,由于 e-mail 地址不合法,因此拋出一個異常"catch" 代碼塊捕獲異常,并顯示錯誤消息13.5 多個異常可以為一段腳本使用多個異常,來檢測多種情況。
可以使用多個 if..else 代碼塊,或一個 switch 代碼塊,或者嵌套多個異常。這些異常能夠使用不同的 exception 類,并返回不同的錯誤消息:
<?phpclass customException extends Exception{public function errorMessage(){//error message$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';return $errorMsg;}}$email = "someone@example.com";try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } //check for "example" in mail address if(strpos($email, "example") !== FALSE) { throw new Exception("$email is an example e-mail"); } }catch (customException $e) { echo $e->errorMessage(); }catch(Exception $e) { echo $e->getMessage(); }?>例子解釋:
上面的代碼測試了兩種條件,如何任何條件不成立,則拋出一個異常:
customException() 類是作為舊的 exception 類的一個擴展來創(chuàng)建的。這樣它就繼承了舊類的所有屬性和方法。創(chuàng)建 errorMessage() 函數(shù)。如果 e-mail 地址不合法,則該函數(shù)返回一個錯誤消息。執(zhí)行 "try" 代碼塊,在第一個條件下,不會拋出異常。由于 e-mail 含有字符串 "example",第二個條件會觸發(fā)異常。"catch" 代碼塊會捕獲異常,并顯示恰當(dāng)?shù)腻e誤消息如果沒有捕獲 customException,緊緊捕獲了 base exception,則在那里處理異常。
13.6 重新拋出異常有時,當(dāng)異常被拋出時,希望以不同于標準的方式對它進行處理。可以在一個 "catch" 代碼塊中再次拋出異常。
腳本應(yīng)該對用戶隱藏系統(tǒng)錯誤。對程序員來說,系統(tǒng)錯誤也許很重要,但是用戶對它們并不感興趣。為了讓用戶更容易使用,您可以再次拋出帶有對用戶比較友好的消息的異常:
<?phpclass customException extends Exception { public function errorMessage() { //error message $errorMsg = $this->getMessage().' is not a valid E-Mail address.'; return $errorMsg; } }$email = "someone@example.com";try { try { //check for "example" in mail address if(strpos($email, "example") !== FALSE) { //throw exception if email is not valid throw new Exception($email); } } catch(Exception $e) { //re-throw exception throw new customException($email); } }catch (customException $e) { //display custom message echo $e->errorMessage(); }?>例子解釋:
上面的代碼檢測在郵件地址中是否含有字符串 "example"。如果有,則再次拋出異常:
customException() 類是作為舊的 exception 類的一個擴展來創(chuàng)建的。這樣它就繼承了舊類的所有屬性和方法。創(chuàng)建 errorMessage() 函數(shù)。如果 e-mail 地址不合法,則該函數(shù)返回一個錯誤消息。把 $email 變量設(shè)置為一個有效的郵件地址,但含有字符串 "example"。"try" 代碼塊包含另一個 "try" 代碼塊,這樣就可以再次拋出異常。由于 e-mail 包含字符串 "example",因此觸發(fā)異常。"catch" 捕獲到該異常,并重新拋出 "customException"。捕獲到 "customException",并顯示一條錯誤消息。如果在其目前的 "try" 代碼塊中異常沒有被捕獲,則它將在更高層級上查找 catch 代碼塊。
13.7 設(shè)置頂層異常處理器 (Top Level Exception Handler)set_exception_handler() 函數(shù)可設(shè)置處理所有未捕獲異常的用戶定義函數(shù)。
<?phpfunction myException($exception){echo "<b>Exception:</b> " , $exception->getMessage();}set_exception_handler('myException');throw new Exception('Uncaught Exception occurred');?>
以上代碼的輸出應(yīng)該類似這樣:
Exception: Uncaught Exception occurred
在上面的代碼中,不存在 "catch" 代碼塊,而是觸發(fā)頂層的異常處理程序。應(yīng)該使用此函數(shù)來捕獲所有未被捕獲的異常。
13.8 異常的規(guī)則需要進行異常處理的代碼應(yīng)該放入 try 代碼塊內(nèi),以便捕獲潛在的異常。每個 try 或 throw 代碼塊必須至少擁有一個對應(yīng)的 catch 代碼塊。使用多個 catch 代碼塊可以捕獲不同種類的異常。可以在 try 代碼塊內(nèi)的 catch 代碼塊中再次拋出(re-thrown)異常。簡而言之:如果拋出了異常,就必須捕獲它。
14、PHP 過濾器(Filter)PHP 過濾器用于驗證和過濾來自非安全來源的數(shù)據(jù),比如用戶的輸入。
14.1 什么是 PHP 過濾器?PHP 過濾器用于驗證和過濾來自非安全來源的數(shù)據(jù)。
驗證和過濾用戶輸入或自定義數(shù)據(jù)是任何 Web 應(yīng)用程序的重要組成部分。
設(shè)計 PHP 的過濾器擴展的目的是使數(shù)據(jù)過濾更輕松快捷。
14.2 為什么使用過濾器?幾乎所有 web 應(yīng)用程序都依賴外部的輸入。這些數(shù)據(jù)通常來自用戶或其他應(yīng)用程序(比如 web 服務(wù))。通過使用過濾器,您能夠確保應(yīng)有程序獲得正確的輸入類型。
您應(yīng)該始終對外部數(shù)據(jù)進行過濾!
輸入過濾是最重要的應(yīng)用程序安全課題之一。
14.2.1 什么是外部數(shù)據(jù)?來自表單的輸入數(shù)據(jù)Cookies服務(wù)器變量數(shù)據(jù)庫查詢結(jié)果14.3 函數(shù)和過濾器如需過濾變量,請使用下面的過濾器函數(shù)之一:
filter_var() - 通過一個指定的過濾器來過濾單一的變量filter_var_array() - 通過相同的或不同的過濾器來過濾多個變量filter_input - 獲取一個輸入變量,并對它進行過濾filter_input_array - 獲取多個輸入變量,并通過相同的或不同的過濾器對它們進行過濾在下面的例子中,用 filter_var() 函數(shù)驗證了一個整數(shù):
<?php$int = 123;if(!filter_var($int, FILTER_VALIDATE_INT)) { echo("Integer is not valid"); }else { echo("Integer is valid"); }?>
上面的代碼使用了 "FILTER_VALIDATE_INT" 過濾器來過濾變量。由于這個整數(shù)是合法的,因此代碼的輸出是:"Integer is valid"。
假如嘗試使用一個非整數(shù)的變量,則輸出是:"Integer is not valid"。
14.4 Validating 和 Sanitizing有兩種過濾器:
14.4.1 Validating 過濾器:用于驗證用戶輸入嚴格的格式規(guī)則(比如 URL 或 E-Mail 驗證)如果成功則返回預(yù)期的類型,如果失敗則返回 FALSE14.4.2 Sanitizing 過濾器:用于允許或禁止字符串中指定的字符無數(shù)據(jù)格式規(guī)則始終返回字符串14.5 選項和標志選項和標志用于向指定的過濾器添加額外的過濾選項。
不同的過濾器有不同的選項和標志。
在下面的例子中,我們用 filter_var() 和 "min_range" 以及 "max_range" 選項驗證了一個整數(shù):
<?php$var=300;$int_options = array("options"=>array ( "min_range"=>0, "max_range"=>256 ));if(!filter_var($var, FILTER_VALIDATE_INT, $int_options)) { echo("Integer is not valid"); }else { echo("Integer is valid"); }?>
就像上面的代碼一樣,選項必須放入一個名為 "options" 的相關(guān)數(shù)組中。如果使用標志,則不需在數(shù)組內(nèi)。
由于整數(shù)是 "300",它不在指定的范圍內(nèi),以上代碼的輸出將是 "Integer is not valid"。
14.6 驗證輸入驗證來自表單的輸入。
首先確認是否存在正在查找的輸入數(shù)據(jù)。
然后用 filter_input() 函數(shù)過濾輸入的數(shù)據(jù)。
在下面的例子中,輸入變量 "email" 被傳到 PHP 頁面:
<?phpif(!filter_has_var(INPUT_GET, "email")) { echo("Input type does not exist"); }else { if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL)) { echo "E-Mail is not valid"; } else { echo "E-Mail is valid"; } }?>例子解釋:
上面的例子有一個通過 "GET" 方法傳送的輸入變量 (email):
檢測是否存在 "GET" 類型的 "email" 輸入變量如果存在輸入變量,檢測它是否是有效的郵件地址14.7 凈化輸入清理從表單傳來的 URL。
首先確認是否存在正在查找的輸入數(shù)據(jù)。
然后,用 filter_input() 函數(shù)來凈化輸入數(shù)據(jù)。
在下面的例子中,輸入變量 "url" 被傳到 PHP 頁面:
<?phpif(!filter_has_var(INPUT_POST, "url")) { echo("Input type does not exist"); }else { $url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL); }?>例子解釋:
上面的例子有一個通過 "POST" 方法傳送的輸入變量 (url):
檢測是否存在 "POST" 類型的 "url" 輸入變量如果存在此輸入變量,對其進行凈化(刪除非法字符),并將其存儲在 $url 變量中假如輸入變量類似這樣:"http://www.W3非o法ol.com.c字符n/",則凈化后的 $url 變量應(yīng)該是這樣的:
http://www.W3School.com.cn/14.8 過濾多個輸入
表單通常由多個輸入字段組成。為了避免對 filter_var 或 filter_input 重復(fù)調(diào)用,可以使用 filter_var_array 或 the filter_input_array 函數(shù)。
在本例中,使用 filter_input_array() 函數(shù)來過濾三個 GET 變量。接收到的 GET 變量是一個名字、一個年齡以及一個郵件地址:
<?php$filters = array ( "name" => array ( "filter"=>FILTER_SANITIZE_STRING ), "age" => array ( "filter"=>FILTER_VALIDATE_INT, "options"=>array ( "min_range"=>1, "max_range"=>120 ) ), "email"=> FILTER_VALIDATE_EMAIL, );$result = filter_input_array(INPUT_GET, $filters);if (!$result["age"]) { echo("Age must be a number between 1 and 120.<br />"); }elseif(!$result["email"]) { echo("E-Mail is not valid.<br />"); }else { echo("User input is valid"); }?>例子解釋:
上面的例子有三個通過 "GET" 方法傳送的輸入變量 (name, age and email)
設(shè)置一個數(shù)組,其中包含了輸入變量的名稱,以及用于指定的輸入變量的過濾器調(diào)用 filter_input_array 函數(shù),參數(shù)包括 GET 輸入變量及剛才設(shè)置的數(shù)組檢測 $result 變量中的 "age" 和 "email" 變量是否有非法的輸入。(如果存在非法輸入,)filter_input_array() 函數(shù)的第二個參數(shù)可以是數(shù)組或單一過濾器的 ID。
如果該參數(shù)是單一過濾器的 ID,那么這個指定的過濾器會過濾輸入數(shù)組中所有的值。
如果該參數(shù)是一個數(shù)組,那么此數(shù)組必須遵循下面的規(guī)則:
必須是一個關(guān)聯(lián)數(shù)組,其中包含的輸入變量是數(shù)組的鍵(比如 "age" 輸入變量)此數(shù)組的值必須是過濾器的 ID ,或者是規(guī)定了過濾器、標志以及選項的數(shù)組14.9 使用 Filter Callback通過使用 FILTER_CALLBACK 過濾器,可以調(diào)用自定義的函數(shù),把它作為一個過濾器來使用。這樣,就擁有了數(shù)據(jù)過濾的完全控制權(quán)。
可以創(chuàng)建自己的自定義函數(shù),也可以使用已有的 PHP 函數(shù)。
規(guī)定準備用到過濾器函數(shù)的方法,與規(guī)定選項的方法相同。
在下面的例子中,使用了一個自定義的函數(shù)把所有 "_" 轉(zhuǎn)換為空格:
<?phpfunction convertSpace($string){return str_replace("_", " ", $string);}$string = "Peter_is_a_great_guy!";echo filter_var($string, FILTER_CALLBACK, array("options"=>"convertSpace"));?>
以上代碼的結(jié)果是這樣的:
Peter is a great guy!例子解釋:
上面的例子把所有 "_" 轉(zhuǎn)換成空格:
創(chuàng)建一個把 "_" 替換為空格的函數(shù)調(diào)用 filter_var() 函數(shù),它的參數(shù)是 FILTER_CALLBACK 過濾器以及包含函數(shù)的數(shù)組PHP編程鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。
新聞熱點
疑難解答
圖片精選