程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> php高級教程,php教程

php高級教程,php教程

編輯:關於PHP編程

php高級教程,php教程


PHP - 多維數組

多維數組指的是包含一個或多個數組的數組。

注釋:數組的維度指示您需要選擇元素的索引數。

  • 對於二維數組,您需要兩個索引來選取元素
  • 對於三維數組,您需要三個索引來選取元素

PHP - 兩維數組

$cars = array
  (
  array("Volvo",22,18),
  array("BMW",15,13),
  array("Saab",5,2),
  array("Land Rover",17,15)
  );
如需訪問 $cars 數組中的元素,我們必須使用兩個索引(行和列):
<?php
echo $cars[0][0].": 庫存:".$cars[0][1].", 銷量:".$cars[0][2].".<br>";
echo $cars[1][0].": 庫存:".$cars[1][1].", 銷量:".$cars[1][2].".<br>";
echo $cars[2][0].": 庫存:".$cars[2][1].", 銷量:".$cars[2][2].".<br>";
echo $cars[3][0].": 庫存:".$cars[3][1].", 銷量:".$cars[3][2].".<br>";
?>
或者:
<?php
for ($row = 0; $row < 4; $row++) {
  echo "<p><b>Row number $row</b></p>";
  echo "<ul>";
  for ($col = 0; $col < 3; $col++) {
    echo "<li>".$cars[$row][$col]."</li>";
  }
  echo "</ul>";
}
?>
PHP date() 函數用於對日期或時間進行格式化。

語法

date(format,timestamp)
參數描述 format 必需。規定時間戳的格式。 timestamp 可選。規定時間戳。默認是當前時間和日期。
<?php
echo "今天是 " . date("Y/m/d") . "<br>";
echo "今天是 " . date("Y.m.d") . "<br>";
echo "今天是 " . date("Y-m-d") . "<br>";
echo "今天是 " . date("l");
?>

PHP 提示 - 自動版權年份

使用 date() 函數在您的網站上自動更新版本年份:

版權所有 2010-<?php echo date("Y")?>

獲得簡單的時間

  • h - 帶有首位零的 12 小時小時格式
  • i - 帶有首位零的分鐘
  • s - 帶有首位零的秒(00 -59)
  • a - 小寫的午前和午後(am 或 pm)
<?php
echo "現在時間是 " . date("h:i:sa");
?>

獲得時區

<?php
date_default_timezone_set("Asia/Shanghai");
echo "當前時間是 " . date("h:i:sa");
?>

通過 PHP mktime() 創建日期

mktime() 函數返回日期的 Unix 時間戳。Unix 時間戳包含 Unix 紀元(1970 年 1 月 1 日 00:00:00 GMT)與指定時間之間的秒數。

語法

mktime(hour,minute,second,month,day,year)
創建日期是 2015-06-10 09:12:31am

通過 PHP strtotime() 用字符串來創建日期

PHP strtotime() 函數用於把人類可讀的字符串轉換為 Unix 時間。

語法

strtotime(time,now)

PHP 在將字符串轉換為日期這方面非常聰明,所以您能夠使用各種值:

實例

<?php
$d=strtotime("tomorrow");
echo date("Y-m-d h:i:sa", $d) . "<br>";
$d=strtotime("next Saturday");
echo date("Y-m-d h:i:sa", $d) . "<br>";
$d=strtotime("+3 Months");
echo date("Y-m-d h:i:sa", $d) . "<br>";
?>
<?php
$d1=strtotime("December 31");
$d2=ceil(($d1-time())/60/60/24);
echo "距離十二月三十一日還有:" . $d2 ." 天。";
?>
服務器端包含 (SSI) 用於創建可在多個頁面重復使用的函數、頁眉、頁腳或元素。

PHP include 和 require 語句

通過 include 或 require 語句,可以將 PHP 文件的內容插入另一個 PHP 文件(在服務器執行它之前)。

include 和 require 語句是相同的,除了錯誤處理方面:

  • require 會生成致命錯誤(E_COMPILE_ERROR)並停止腳本
  • include 只生成警告(E_WARNING),並且腳本會繼續

假設我們有一個名為 "footer.php" 的標准的頁腳文件,就像這樣:

<?php
echo "<p>Copyright © 2006-" . date("Y") . " W3School.com.cn</p>";
?>

如需在一張頁面中引用這個頁腳文件,請使用 include 語句:

<html>
<body>
<h1>歡迎訪問我們的首頁!</h1>
<p>一段文本。</p>
<p>一段文本。</p>
<?php include 'footer.php';?>
</body>
</html>

PHP 操作文件

PHP 擁有的多種函數可供創建、讀取、上傳以及編輯文件。

注意:請謹慎操作文件!

當您操作文件時必須非常小心。如果您操作失誤,可能會造成非常嚴重的破壞。常見的錯誤是:

  • 編輯錯誤的文件
  • 被垃圾數據填滿硬盤
  • 意外刪除文件內容

PHP readfile() 函數

readfile() 函數讀取文件,並把它寫入輸出緩沖。

假設我們有一個名為 "webdictionary.txt" 的文本文件,存放在服務器上,就像這樣:

AJAX = Asynchronous JavaScript and XML
CSS = Cascading Style Sheets
HTML = Hyper Text Markup Language
PHP = PHP Hypertext Preprocessor
SQL = Structured Query Language
SVG = Scalable Vector Graphics
XML = EXtensible Markup Language

讀取此文件並寫到輸出流的 PHP 代碼如下(如讀取成功則 readfile() 函數返回字節數):

實例

<?php
echo readfile("webdictionary.txt");
?>

PHP Open File - fopen()

fopen() 的第一個參數包含被打開的文件名,第二個參數規定打開文件的模式。如果 fopen() 函數未能打開指定的文件,下面的例子會生成一段消息:
<?php
$myfile = fopen("webdictionary.txt", "r") or die("Unable to open file!");
echo fread($myfile,filesize("webdictionary.txt"));
fclose($myfile);
?>

文件會以如下模式之一打開:

模式描述 r 打開文件為只讀。文件指針在文件的開頭開始。 w 打開文件為只寫。刪除文件的內容或創建一個新的文件,如果它不存在。文件指針在文件的開頭開始。 a 打開文件為只寫。文件中的現有數據會被保留。文件指針在文件結尾開始。創建新的文件,如果文件不存在。 x 創建新文件為只寫。返回 FALSE 和錯誤,如果文件已存在。 r+ 打開文件為讀/寫、文件指針在文件開頭開始。 w+ 打開文件為讀/寫。刪除文件內容或創建新文件,如果它不存在。文件指針在文件開頭開始。 a+ 打開文件為讀/寫。文件中已有的數據會被保留。文件指針在文件結尾開始。創建新文件,如果它不存在。 x+ 創建新文件為讀/寫。返回 FALSE 和錯誤,如果文件已存在。

PHP 讀取文件 - fread()

fread() 的第一個參數包含待讀取文件的文件名,第二個參數規定待讀取的最大字節數。

如下 PHP 代碼把 "webdictionary.txt" 文件讀至結尾:

fread($myfile,filesize("webdictionary.txt"));

PHP 關閉文件 - fclose()

注釋:用完文件後把它們全部關閉是一個良好的編程習慣。您並不想打開的文件占用您的服務器資源。

fclose() 需要待關閉文件的名稱(或者存有文件名的變量):

<?php
$myfile = fopen("webdictionary.txt", "r");
// some code to be executed....
fclose($myfile);
?>

PHP 讀取單行文件 - fgets()

下例輸出 "webdictionary.txt" 文件的首行:
<?php
$myfile = fopen("webdictionary.txt", "r") or die("Unable to open file!");
echo fgets($myfile);
fclose($myfile);
?>
注釋:調用 fgets() 函數之後,文件指針會移動到下一行。

PHP 檢查 End-Of-File - feof()

feof() 對於遍歷未知長度的數據很有用。

下例逐行讀取 "webdictionary.txt" 文件,直到 end-of-file:

<?php
$myfile = fopen("webdictionary.txt", "r") or die("Unable to open file!");
// 輸出單行直到 end-of-file
while(!feof($myfile)) {
  echo fgets($myfile) . "<br>";
}
fclose($myfile);
?>

PHP 讀取單字符 - fgetc()

下例逐字符讀取 "webdictionary.txt" 文件,直到 end-of-file:
<?php
$myfile = fopen("webdictionary.txt", "r") or die("Unable to open file!");
// 輸出單字符直到 end-of-file
while(!feof($myfile)) {
  echo fgetc($myfile);
}
fclose($myfile);
?>
注釋:在調用 fgetc() 函數之後,文件指針會移動到下一個字符。

PHP 創建文件 - fopen()

如果您用 fopen() 打開並不存在的文件,此函數會創建文件,假定文件被打開為寫入(w)或增加(a)。

下面的例子創建名為 "testfile.txt" 的新文件。此文件將被創建於 PHP 代碼所在的相同目錄中:

$myfile = fopen("testfile.txt", "w")

PHP 文件權限

如果您試圖運行這段代碼時發生錯誤,請檢查您是否有向硬盤寫入信息的 PHP 文件訪問權限。

PHP 寫入文件 - fwrite()

fwrite() 的第一個參數包含要寫入的文件的文件名,第二個參數是被寫的字符串。
<?php
$myfile = fopen("newfile.txt", "w") or die("Unable to open file!");
$txt = "Bill Gates\n";
fwrite($myfile, $txt);
$txt = "Steve Jobs\n";
fwrite($myfile, $txt);
fclose($myfile);
?>

PHP 覆蓋(Overwriting)

如果現在 "newfile.txt" 包含了一些數據,我們可以展示在寫入已有文件時發生的的事情。所有已存在的數據會被擦除並以一個新文件開始。

<?php
$myfile = fopen("newfile.txt", "w") or die("Unable to open file!");
$txt = "Mickey Mouse\n";
fwrite($myfile, $txt);
$txt = "Minnie Mouse\n";
fwrite($myfile, $txt);
fclose($myfile);
?>

創建上傳腳本

"upload_file.php" 文件含有供上傳文件的代碼:

<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo "Error: " . $_FILES["file"]["error"] . "<br />";
  }
else
  {
  echo "Upload: " . $_FILES["file"]["name"] . "<br />";
  echo "Type: " . $_FILES["file"]["type"] . "<br />";
  echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES["file"]["tmp_name"];
  }
?>
  • $_FILES["file"]["name"] - 被上傳文件的名稱
  • $_FILES["file"]["type"] - 被上傳文件的類型
  • $_FILES["file"]["size"] - 被上傳文件的大小,以字節計
  • $_FILES["file"]["tmp_name"] - 存儲在服務器的文件的臨時副本的名稱
  • $_FILES["file"]["error"] - 由文件上傳導致的錯誤代碼

上傳限制

在這個腳本中,我們增加了對文件上傳的限制。用戶只能上傳 .gif 或 .jpeg 文件,文件大小必須小於 20 kb:

<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Error: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Stored in: " . $_FILES["file"]["tmp_name"];
    }
  }
else
  {
  echo "Invalid file";
  }
?>

注釋:對於 IE,識別 jpg 文件的類型必須是 pjpeg,對於 FireFox,必須是 jpeg。

保存被上傳的文件

上面的例子在服務器的 PHP 臨時文件夾創建了一個被上傳文件的臨時副本。

這個臨時的復制文件會在腳本結束時消失。要保存被上傳的文件,我們需要把它拷貝到另外的位置:

<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

上面的腳本檢測了是否已存在此文件,如果不存在,則把文件拷貝到指定的文件夾。

注釋:這個例子把文件保存到了名為 "upload" 的新文件夾。

cookie 常用於識別用戶。

setcookie() 函數用於設置 cookie。

注釋:setcookie() 函數必須位於 <html> 標簽之前。

語法

setcookie(name, value, expire, path, domain);

在下面的例子中,我們將創建名為 "user" 的 cookie,把為它賦值 "Alex Porter"。我們也規定了此 cookie 在一小時後過期:

<?php 
setcookie("user", "Alex Porter", time()+3600);
?>
注釋:在發送 cookie 時,cookie 的值會自動進行 URL 編碼,在取回時進行自動解碼(為防止 URL 編碼,請使用 setrawcookie() 取而代之)。
PHP 的 $_COOKIE 變量用於取回 cookie 的值。

在下面的例子中,我們取回了名為 "user" 的 cookie 的值,並把它顯示在了頁面上:

<?php
// Print a cookie
echo $_COOKIE["user"];
// A way to view all cookies
print_r($_COOKIE);
?>

在下面的例子中,我們使用 isset() 函數來確認是否已設置了 cookie:

<html>
<body>
<?php
if (isset($_COOKIE["user"]))
  echo "Welcome " . $_COOKIE["user"] . "!<br />";
else
  echo "Welcome guest!<br />";
?>
</body>
</html>
當刪除 cookie 時,您應當使過期日期變更為過去的時間點。
<?php 
// set the expiration date to one hour ago
setcookie("user", "", time()-3600);
?>
PHP session 變量用於存儲有關用戶會話的信息,或更改用戶會話的設置。Session 變量保存的信息是單一用戶的,並且可供應用程序中的所有頁面使用。
不過,會話信息是臨時的,在用戶離開網站後將被刪除。如果您需要永久儲存信息,可以把數據存儲在數據庫中。
Session 的工作機制是:為每個訪問者創建一個唯一的 id (UID),並基於這個 UID 來存儲變量。UID 存儲在 cookie 中,亦或通過 URL 進行傳導。

在您把用戶信息存儲到 PHP session 中之前,首先必須啟動會話。

注釋:session_start() 函數必須位於 <html> 標簽之前

存儲 Session 變量

存儲和取回 session 變量的正確方法是使用 PHP $_SESSION 變量:

<?php
session_start();
// store session data
$_SESSION['views']=1;
?>
<html>
<body>
<?php
//retrieve session data
echo "Pageviews=". $_SESSION['views'];
?>
</body>
</html>

輸出:

Pageviews=1

終結 Session

如果您希望刪除某些 session 數據,可以使用 unset() 或 session_destroy() 函數。

unset() 函數用於釋放指定的 session 變量:

<?php
unset($_SESSION['views']);
?>

您也可以通過 session_destroy() 函數徹底終結 session:

<?php
session_destroy();
?>

注釋:session_destroy() 將重置 session,您將失去所有已存儲的 session 數據。

PHP mail() 函數

PHP mail() 函數用於從腳本中發送電子郵件。

語法

mail(to,subject,message,headers,parameters)
參數描述 to 必需。規定 email 接收者。 subject 必需。規定 email 的主題。注釋:該參數不能包含任何新行字符。 message 必需。定義要發送的消息。應使用 LF (\n) 來分隔各行。 headers

可選。規定附加的標題,比如 From、Cc 以及 Bcc。

應當使用 CRLF (\r\n) 分隔附加的標題。

parameters 可選。對郵件發送程序規定額外的參數。 注釋:PHP 需要一個已安裝且正在運行的郵件系統,以便使郵件函數可用。所用的程序通過在 php.ini 文件中的配置設置進行定義。

PHP 簡易 E-Mail

通過 PHP 發送電子郵件的最簡單的方式是發送一封文本 email。

在下面的例子中,我們首先聲明變量($to, $subject, $message, $from, $headers),然後我們在 mail() 函數中使用這些變量來發送了一封 e-mail:

<?php
$to = "[email protected]";
$subject = "Test mail";
$message = "Hello! This is a simple email message.";
$from = "[email protected]";
$headers = "From: $from";
mail($to,$subject,$message,$headers);
echo "Mail Sent.";
?>

PHP Mail Form

通過 PHP,您能夠在自己的站點制作一個反饋表單。下面的例子向指定的 e-mail 地址發送了一條文本消息:

<html>
<body>

<?php
if (isset($_REQUEST['email']))
//if "email" is filled out, send email
  {
  //send email
  $email = $_REQUEST['email'] ; 
  $subject = $_REQUEST['subject'] ;
  $message = $_REQUEST['message'] ;
  mail( "[email protected]", "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>

例子解釋:

  1. 首先,檢查是否填寫了郵件輸入框
  2. 如果未填寫(比如在頁面被首次訪問時),輸出 HTML 表單
  3. 如果已填寫(在表單被填寫後),從表單發送郵件
  4. 當點擊提交按鈕後,重新載入頁面,顯示郵件發送成功的消息

PHP 防止 E-mail 注入

防止 e-mail 注入的最好方法是對輸入進行驗證。

<html>
<body>
<?php
function 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("[email protected]", "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 驗證電子郵件地址
在 PHP 中,默認的錯誤處理很簡單。一條消息會被發送到浏覽器,這條消息帶有文件名、行號以及一條描述錯誤的消息。

基本的錯誤處理:使用 die() 函數    

die("File not found");

創建自定義錯誤處理器

創建一個自定義的錯誤處理器非常簡單。我們很簡單地創建了一個專用函數,可以在 PHP 中發生錯誤時調用該函數。

該函數必須有能力處理至少兩個參數 (error level 和 error message),但是可以接受最多五個參數(可選的:file, line-number 以及 error context):

語法

error_function(error_level,error_message,
error_file,error_line,error_context)
參數描述 error_level

必需。為用戶定義的錯誤規定錯誤報告級別。必須是一個值數。

參見下面的表格:錯誤報告級別。

error_message 必需。為用戶定義的錯誤規定錯誤消息。 error_file 可選。規定錯誤在其中發生的文件名。 error_line 可選。規定錯誤發生的行號。 error_context 可選。規定一個數組,包含了當錯誤發生時在用的每個變量以及它們的值。

錯誤報告級別

值常量描述 2 E_WARNING 非致命的 run-time 錯誤。不暫停腳本執行。 8 E_NOTICE

Run-time 通知。

腳本發現可能有錯誤發生,但也可能在腳本正常運行時發生。

256 E_USER_ERROR 致命的用戶生成的錯誤。這類似於程序員使用 PHP 函數 trigger_error() 設置的 E_ERROR。 512 E_USER_WARNING 非致命的用戶生成的警告。這類似於程序員使用 PHP 函數 trigger_error() 設置的 E_WARNING。 1024 E_USER_NOTICE 用戶生成的通知。這類似於程序員使用 PHP 函數 trigger_error() 設置的 E_NOTICE。 4096 E_RECOVERABLE_ERROR 可捕獲的致命錯誤。類似 E_ERROR,但可被用戶定義的處理程序捕獲。(參見 set_error_handler()) 8191 E_ALL

所有錯誤和警告,除級別 E_STRICT 以外。

(在 PHP 6.0,E_STRICT 是 E_ALL 的一部分)

function customError($errno, $errstr)
 { 
 echo "<b>Error:</b> [$errno] $errstr<br />";
 echo "Ending Script";
 die();
 }

上面的代碼是一個簡單的錯誤處理函數。當它被觸發時,它會取得錯誤級別和錯誤消息。然後它會輸出錯誤級別和消息,並終止腳本。

Set Error Handler

PHP 的默認錯誤處理程序是內建的錯誤處理程序。我們打算把上面的函數改造為腳本運行期間的默認錯誤處理程序。

可以修改錯誤處理程序,使其僅應用到某些錯誤,這樣腳本就可以不同的方式來處理不同的錯誤。不過,在本例中,我們打算針對所有錯誤來使用我們的自定義錯誤處理程序:

set_error_handler("customError");

由於我們希望我們的自定義函數來處理所有錯誤,set_error_handler() 僅需要一個參數,可以添加第二個參數來規定錯誤級別。

觸發錯誤

在腳本中用戶輸入數據的位置,當用戶的輸入無效時觸發錯誤的很有用的。在 PHP 中,這個任務由 trigger_error() 完成。

您可以在腳本中任何位置觸發錯誤,通過添加的第二個參數,您能夠規定所觸發的錯誤級別。

可能的錯誤類型:

  • E_USER_ERROR - 致命的用戶生成的 run-time 錯誤。錯誤無法恢復。腳本執行被中斷。
  • E_USER_WARNING - 非致命的用戶生成的 run-time 警告。腳本執行不被中斷。
  • E_USER_NOTICE - 默認。用戶生成的 run-time 通知。腳本發現了可能的錯誤,也有可能在腳本運行正常時發生。

錯誤記錄

默認地,根據在 php.ini 中的 error_log 配置,PHP 向服務器的錯誤記錄系統或文件發送錯誤記錄。通過使用 error_log() 函數,您可以向指定的文件或遠程目的地發送錯誤記錄。

通過電子郵件向您自己發送錯誤消息,是一種獲得指定錯誤的通知的好辦法。

通過 E-Mail 發送錯誤消息

在下面的例子中,如果特定的錯誤發生,我們將發送帶有錯誤消息的電子郵件,並結束腳本:

<?php
//error handler function
function customError($errno, $errstr)
 { 
 echo "<b>Error:</b> [$errno] $errstr<br />";
 echo "Webmaster has been notified";
 error_log("Error: [$errno] $errstr",1,
 "[email protected]","From: [email protected]");
}

//set error handler
set_error_handler("customError",E_USER_WARNING);

//trigger error
$test=2;
if ($test>1)
 {
 trigger_error("Value must be 1 or below",E_USER_WARNING);
 }
?>

以上代碼的輸出應該類似這樣:

Error: [512] Value must be 1 or below
Webmaster has been notified

接收自以上代碼的郵件類似這樣:

Error: [512] Value must be 1 or below

這個方法不適合所有的錯誤。常規錯誤應當通過使用默認的 PHP 記錄系統在服務器上進行記錄。

異常(Exception)用於在指定的錯誤發生時改變腳本的正常流程。

當異常被觸發時,通常會發生:

  • 當前代碼狀態被保存
  • 代碼執行被切換到預定義的異常處理器函數
  • 根據情況,處理器也許會從保存的代碼狀態重新開始執行代碼,終止腳本執行,或從代碼中另外的位置繼續執行腳本

異常的基本使用

當異常被拋出時,其後的代碼不會繼續執行,PHP 會嘗試查找匹配的 "catch" 代碼塊。

如果異常沒有被捕獲,而且又沒用使用 set_exception_handler() 作相應的處理的話,那麼將發生一個嚴重的錯誤(致命錯誤),並且輸出 "Uncaught Exception" (未捕獲異常)的錯誤消息。

正確的處理程序應當包括:

  1. Try - 使用異常的函數應該位於 "try" 代碼塊內。如果沒有觸發異常,則代碼將照常繼續執行。但是如果異常被觸發,會拋出一個異常。
  2. Throw - 這裡規定如何觸發異常。每一個 "throw" 必須對應至少一個 "catch"
  3. Catch - "catch" 代碼塊會捕獲異常,並創建一個包含異常信息的對象

創建一個自定義的 Exception 類

這個自定義的 exception 類繼承了 PHP 的 exception 類的所有屬性,您可向其添加自定義的函數。
<?php
class 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 = "[email protected]";

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 類來捕獲它:

  1. customException() 類是作為舊的 exception 類的一個擴展來創建的。這樣它就繼承了舊類的所有屬性和方法。
  2. 創建 errorMessage() 函數。如果 e-mail 地址不合法,則該函數返回一條錯誤消息
  3. 把 $email 變量設置為不合法的 e-mail 地址字符串
  4. 執行 "try" 代碼塊,由於 e-mail 地址不合法,因此拋出一個異常
  5. "catch" 代碼塊捕獲異常,並顯示錯誤消息

多個異常

可以使用多個 if..else 代碼塊,或一個 switch 代碼塊,或者嵌套多個異常。這些異常能夠使用不同的 exception 類,並返回不同的錯誤消息:
<?php
class 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 = "[email protected]";

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();
 }
?>

例子解釋:

上面的代碼測試了兩種條件,如何任何條件不成立,則拋出一個異常:

  1. customException() 類是作為舊的 exception 類的一個擴展來創建的。這樣它就繼承了舊類的所有屬性和方法。
  2. 創建 errorMessage() 函數。如果 e-mail 地址不合法,則該函數返回一個錯誤消息。
  3. 執行 "try" 代碼塊,在第一個條件下,不會拋出異常。
  4. 由於 e-mail 含有字符串 "example",第二個條件會觸發異常。
  5. "catch" 代碼塊會捕獲異常,並顯示恰當的錯誤消息

如果沒有捕獲 customException,緊緊捕獲了 base exception,則在那裡處理異常。

重新拋出異常

有時,當異常被拋出時,您也許希望以不同於標准的方式對它進行處理。可以在一個 "catch" 代碼塊中再次拋出異常。

腳本應該對用戶隱藏系統錯誤。對程序員來說,系統錯誤也許很重要,但是用戶對它們並不感興趣。為了讓用戶更容易使用,您可以再次拋出帶有對用戶比較友好的消息的異常:

<?php
class customException extends Exception
 {
 public function errorMessage()
  {
  //error message
  $errorMsg = $this->getMessage().' is not a valid E-Mail address.';
  return $errorMsg;
  }
 }

$email = "[email protected]";

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"。如果有,則再次拋出異常:

  1. customException() 類是作為舊的 exception 類的一個擴展來創建的。這樣它就繼承了舊類的所有屬性和方法。
  2. 創建 errorMessage() 函數。如果 e-mail 地址不合法,則該函數返回一個錯誤消息。
  3. 把 $email 變量設置為一個有效的郵件地址,但含有字符串 "example"。
  4. "try" 代碼塊包含另一個 "try" 代碼塊,這樣就可以再次拋出異常。
  5. 由於 e-mail 包含字符串 "example",因此觸發異常。
  6. "catch" 捕獲到該異常,並重新拋出 "customException"。
  7. 捕獲到 "customException",並顯示一條錯誤消息。

如果在其目前的 "try" 代碼塊中異常沒有被捕獲,則它將在更高層級上查找 catch 代碼塊。

設置頂層異常處理器 (Top Level Exception Handler)

set_exception_handler() 函數可設置處理所有未捕獲異常的用戶定義函數。

<?php
function myException($exception)
{
echo "<b>Exception:</b> " , $exception->getMessage();
}

set_exception_handler('myException');

throw new Exception('Uncaught Exception occurred');
?>

以上代碼的輸出應該類似這樣:

Exception: Uncaught Exception occurred

在上面的代碼中,不存在 "catch" 代碼塊,而是觸發頂層的異常處理程序。應該使用此函數來捕獲所有未被捕獲的異常。

異常的規則

  • 需要進行異常處理的代碼應該放入 try 代碼塊內,以便捕獲潛在的異常。
  • 每個 try 或 throw 代碼塊必須至少擁有一個對應的 catch 代碼塊。
  • 使用多個 catch 代碼塊可以捕獲不同種類的異常。
  • 可以在 try 代碼塊內的 catch 代碼塊中再次拋出(re-thrown)異常。

簡而言之:如果拋出了異常,就必須捕獲它。

PHP 過濾器用於驗證和過濾來自非安全來源的數據,比如用戶的輸入。

您應該始終對外部數據進行過濾!

什麼是外部數據?

  • 來自表單的輸入數據
  • Cookies
  • 服務器變量
  • 數據庫查詢結果

函數和過濾器

如需過濾變量,請使用下面的過濾器函數之一:

  • filter_var() - 通過一個指定的過濾器來過濾單一的變量
  • filter_var_array() - 通過相同的或不同的過濾器來過濾多個變量
  • filter_input - 獲取一個輸入變量,並對它進行過濾
  • filter_input_array - 獲取多個輸入變量,並通過相同的或不同的過濾器對它們進行過濾

在下面的例子中,我們用 filter_var() 函數驗證了一個整數:

<?php
$int = 123;

if(!filter_var($int, FILTER_VALIDATE_INT))
 {
 echo("Integer is not valid");
 }
else
 {
 echo("Integer is valid");
 }
?>

Validating 和 Sanitizing

有兩種過濾器:

Validating 過濾器:

  • 用於驗證用戶輸入
  • 嚴格的格式規則(比如 URL 或 E-Mail 驗證)
  • 如果成功則返回預期的類型,如果失敗則返回 FALSE

Sanitizing 過濾器:

  • 用於允許或禁止字符串中指定的字符
  • 無數據格式規則
  • 始終返回字符串

選項和標志

選項和標志用於向指定的過濾器添加額外的過濾選項。

不同的過濾器有不同的選項和標志。

在下面的例子中,我們用 filter_var() 和 "min_range" 以及 "max_range" 選項驗證了一個整數:

<?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");
 }
?>

驗證輸入

我們需要作的第一件事情是確認是否存在我們正在查找的輸入數據。

然後我們用 filter_input() 函數過濾輸入的數據。

在下面的例子中,輸入變量 "email" 被傳到 PHP 頁面:

<?php
if(!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):

  1. 檢測是否存在 "GET" 類型的 "email" 輸入變量
  2. 如果存在輸入變量,檢測它是否是有效的郵件地址

淨化輸入

讓我們試著清理一下從表單傳來的 URL。

首先,我們要確認是否存在我們正在查找的輸入數據。

然後,我們用 filter_input() 函數來淨化輸入數據。

在下面的例子中,輸入變量 "url" 被傳到 PHP 頁面:

<?php
if(!filter_has_var(INPUT_POST, "url"))
 {
 echo("Input type does not exist");
 }
else
 {
 $url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL);
 }
?>

例子解釋:

上面的例子有一個通過 "POST" 方法傳送的輸入變量 (url):

  1. 檢測是否存在 "POST" 類型的 "url" 輸入變量
  2. 如果存在此輸入變量,對其進行淨化(刪除非法字符),並將其存儲在 $url 變量中

假如輸入變量類似這樣:"http://www.W3非o法ol.com.c字符n/",則淨化後的 $url 變量應該是這樣的:

http://www.W3School.com.cn/

過濾多個輸入

表單通常由多個輸入字段組成。為了避免對 filter_var 或 filter_input 重復調用,我們可以使用 filter_var_array 或 the filter_input_array 函數。

在本例中,我們使用 filter_input_array() 函數來過濾三個 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)

  1. 設置一個數組,其中包含了輸入變量的名稱,以及用於指定的輸入變量的過濾器
  2. 調用 filter_input_array 函數,參數包括 GET 輸入變量及剛才設置的數組
  3. 檢測 $result 變量中的 "age" 和 "email" 變量是否有非法的輸入。(如果存在非法輸入,)

filter_input_array() 函數的第二個參數可以是數組或單一過濾器的 ID。

如果該參數是單一過濾器的 ID,那麼這個指定的過濾器會過濾輸入數組中所有的值。

如果該參數是一個數組,那麼此數組必須遵循下面的規則:

  • 必須是一個關聯數組,其中包含的輸入變量是數組的鍵(比如 "age" 輸入變量)
  • 此數組的值必須是過濾器的 ID ,或者是規定了過濾器、標志以及選項的數組

使用 Filter Callback

通過使用 FILTER_CALLBACK 過濾器,可以調用自定義的函數,把它作為一個過濾器來使用。這樣,我們就擁有了數據過濾的完全控制權。

您可以創建自己的自定義函數,也可以使用已有的 PHP 函數。

規定您准備用到過濾器函數的方法,與規定選項的方法相同。

在下面的例子中,我們使用了一個自定義的函數把所有 "_" 轉換為空格:

<?php
function convertSpace($string)
{
return str_replace("_", " ", $string);
}

$string = "Peter_is_a_great_guy!";

echo filter_var($string, FILTER_CALLBACK, array("options"=>"convertSpace"));
?>

以上代碼的結果是這樣的:

Peter is a great guy!

例子解釋:

上面的例子把所有 "_" 轉換成空格:

  1. 創建一個把 "_" 替換為空格的函數
  2. 調用 filter_var() 函數,它的參數是 FILTER_CALLBACK 過濾器以及包含我們的函數的數組

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved