十天学会PHP/第九天:错误处理、异常处理、过滤器

来自站长百科
跳转至: 导航、​ 搜索

十天学会PHP

PHP 错误处理[ ]

  • 在创建脚本和web应用程序时,错误处理是一个重要的部分。如果您的代码缺少错误检测编码,那么程序看上去很不专业,也为安全风险敞开了大门。
  • 本教程介绍了 PHP 中一些最为重要的错误检测方法。
  • 我们将为您讲解不同的错误处理方法:
  1. 简单的 "die()" 语句
  2. 自定义错误和错误触发器
  3. 错误报告
  4. 基本的错误处理:使用 die() 函数
  • 第一个例子展示了一个打开文本文件的简单脚本:
<?php
$file=fopen("welcome.txt","r");
?>
  • 如果文件不存在,您会获得类似这样的错误:
Warning: fopen(welcome.txt) [function.fopen]: failed to open stream: 
No such file or directory in C:\webfolder\test.php on line 2
  • 为了避免用户获得类似上面的错误消息,我们在访问文件之前检测该文件是否存在:
<?php
if(!file_exists("welcome.txt"))
 {
 die("File not found");
 }
else
 {
 $file=fopen("welcome.txt","r");
 }
?>
  • 现在,假如文件不存在,您会得到类似这样的错误消息:
  • File not found比起之前的代码,上面的代码更有效,这是由于它采用了一个简单的错误处理机制在错误之后终止了脚本。
  • 不过,简单地终止脚本并不总是恰当的方式。让我们研究一下用于处理错误的备选的 PHP 函数。

创建自定义错误处理器[ ]

  • 创建一个自定义的错误处理器非常简单。我们很简单地创建了一个专用函数,可以在 PHP 中发生错误时调用该函数。
  • 该函数必须有能力处理至少两个参数 (error level 和 error message),但是可以接受最多五个参数(可选的:file, line-number 以及 error context):
  • 语法
error_function(error_level,error_message,
error_file,error_line,error_context)

PHP错误处理参数.jpg

  • 错误报告级别
  • 这些错误报告级别是错误处理程序旨在处理的错误的不同的类型:

PHP错误报告级别.jpg

  • 现在,让我们创建一个处理错误的函数:
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
//error handler function
function customError($errno, $errstr)
 { 
 echo "<b>Error:</b> [$errno] $errstr";
 }

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

//trigger error
echo($test);
?>
  • 以上代码的输出应该类似这样:
  • Error: [8] Undefined variable: test触发错误
  • 在脚本中用户输入数据的位置,当用户的输入无效时触发错误的很有用的。在 PHP 中,这个任务由 trigger_error() 完成。
  • 例子
  • 在本例中,如果 "test" 变量大于 "1",就会发生错误:
<?php
$test=2;
if ($test>1)
{
trigger_error("Value must be 1 or below");
}
?>
  • 以上代码的输出应该类似这样:
Notice: Value must be 1 or below
in C:\webfolder\test.php on line 6
  • 您可以在脚本中任何位置触发错误,通过添加的第二个参数,您能够规定所触发的错误级别。
  • 可能的错误类型:
  • E_USER_ERROR - 致命的用户生成的 run-time 错误。错误无法恢复。脚本执行被中断。
  • E_USER_WARNING - 非致命的用户生成的 run-time 警告。脚本执行不被中断。
  • E_USER_NOTICE - 默认。用户生成的 run-time 通知。脚本发现了可能的错误,也有可能在脚本运行正常时发生。
  • 例子
  • 在本例中,如果 "test" 变量大于 "1",则发生 E_USER_WARNING 错误。如果发生了 E_USER_WARNING,我们将使用我们的自定义错误处理程序并结束脚本:
<?php
//error handler function
function customError($errno, $errstr)
 { 
 echo "<b>Error:</b> [$errno] $errstr<br />";
 echo "Ending Script";
 die();
 }

//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
Ending Script
  • 现在,我们已经学习了如何创建自己的 error,以及如何处罚它们,现在我们研究一下错误记录。

错误记录[ ]

  • 默认地,根据在 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,
 "someone@example.com","From: webmaster@example.com");
}

//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 记录系统在服务器上进行记录。

什么是 PHP 过滤器?[ ]

  • PHP 过滤器用于验证和过滤来自非安全来源的数据。
  • 验证和过滤用户输入或自定义数据是任何 Web 应用程序的重要组成部分。
  • 设计 PHP 的过滤器扩展的目的是使数据过滤更轻松快捷。

为什么使用过滤器?[ ]

  • 几乎所有 web 应用程序都依赖外部的输入。这些数据通常来自用户或其他应用程序(比如 web 服务)。通过使用过滤器,您能够确保应有程序获得正确的输入类型。
  • 您应该始终对外部数据进行过滤!
  • 输入过滤是最重要的应用程序安全课题之一。

什么是外部数据?[ ]

  • 来自表单的输入数据
  • Cookies
  • 服务器变量
  • 数据库查询结果
  • 函数和过滤器
  • 如需过滤变量,请使用下面的过滤器函数之一
  1. filter_var() - 通过一个指定的过滤器来过滤单一的变量
  2. filter_var_array() - 通过相同的或不同的过滤器来过滤多个变量
  3. filter_input - 获取一个输入变量,并对它进行过滤
  4. 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");
 }
?>
  • 上面的代码使用了 "FILTER_VALIDATE_INT" 过滤器来过滤变量。由于这个整数是合法的,因此代码的输出是:"Integer is valid"。
  • 假如我们尝试使用一个非整数的变量,则输出是:"Integer is not valid"。
  • 如需完整的函数和过滤器列表,请访问我们的 PHP Filter 参考手册。

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");
 }
?>
  • 就像上面的代码一样,选项必须放入一个名为 "options" 的相关数组中。如果使用标志,则不需在数组内。
  • 由于整数是 "300",它不在指定的氛围内,以上代码的输出将是 "Integer is not valid"。
  • 如需完整的函数及过滤器列表,请访问 W3School 提供的 PHP Filter 参考手册。您可以看到每个过滤器的可用选项和标志。

验证输入[ ]

  • 让我们试着验证来自表单的输入。
  • 我们需要作的第一件事情是确认是否存在我们正在查找的输入数据。
  • 然后我们用 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):
  • 检测是否存在 "GET" 类型的 "email" 输入变量
  • 如果存在输入变量,检测它是否是有效的邮件地址

净化输入[ ]

  • 让我们试着清理一下从表单传来的 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):
  • 检测是否存在 "POST" 类型的 "url" 输入变量
  • 如果存在此输入变量,对其进行净化(删除非法字符),并将其存储在 $url 变量中
  • 假如输入变量类似这样:"http://www.W3#$%S^%$#ool.com.cn/",则净化后的 $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)
  • 设置一个数组,其中包含了输入变量的名称,以及用于指定的输入变量的过滤器
  • 调用 filter_input_array 函数,参数包括 GET 输入变量及刚才设置的数组
  • 检测 $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!例子解释:
  • 上面的例子把所有 "_" 转换成空格:
  • 创建一个把 "_" 替换为空格的函数
  • 调用 filter_var() 函数,它的参数是 FILTER_CALLBACK 过滤器以及包含我们的函数的数组

参考来源[ ]

使用手册导航

十天学会php

第一天:PHP基础教程|第二天:PHP基础语法|第三天:运算符、循环与数组|第四天:数组、函数、表单|第五天:$_GET、$_POST |第六天:PHP日期、引用|第七天:文件上传、Cookies|第八天:Sessions、发送电子邮件|第九天:错误处理、异常处理、过滤器|第十天:PHP学习必看