当前位置: 移动技术网 > IT编程>开发语言>PHP > Php高级知识 2

Php高级知识 2

2018年09月21日  | 移动技术网IT编程  | 我要评论

8、php cookies

cookie 常用于识别用户。

8.1 什么是 cookie?

cookie 常用于识别用户。cookie 是服务器留在用户计算机中的小文件。每当相同的计算机通过请求页面时,它同时会发送 cookie。通过 php,您能够创建并取回 cookie 的值。

8.2 如何创建 cookie?

setcookie() 函数用于设置 cookie。

注释:setcookie() 函数必须位于

标签之前。

语法

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

例子

在下面的例子中,我们将创建名为 "user" 的 cookie,把为它赋值 "alex porter"。我们也规定了此 cookie 在一小时后过期:



注释:在发送 cookie 时,cookie 的值会自动进行 url 编码,在取回时进行自动解码(为防止 url 编码,请使用 setrawcookie() 取而代之)。

8.3 如何取回 cookie 的值?

php 的 $_cookie 变量用于取回 cookie 的值。

在下面的例子中,我们取回了名为 "user" 的 cookie 的值,并把它显示在了页面上:

在下面的例子中,我们使用 isset() 函数来确认是否已设置了 cookie:


"; else echo "welcome guest!
"; ?>

8.4 如何删除 cookie?

当删除 cookie 时,您应当使过期日期变更为过去的时间点。

删除的例子:

8.5 如果浏览器不支持 cookie 该怎么办?

如果应用程序涉及不支持 cookie 的浏览器,应采取其他方法在应用程序中从一张页面向另一张页面传递信息。一种方式是从表单传递数据(有关表单和用户输入的内容,在前面已介绍过了)。

下面的表单在用户单击提交按钮时向 "welcome.php" 提交了用户输入:
 

<form action="welcome.php" method="post">
name: <input type="text" name="name">
age: <input type="text" name="age">
<input type="submit">
</form>

 

取回 "welcome.php" 中的值,就像这样:


welcome .
you are years old.

 

9、php sessions

php session 变量用于存储有关用户会话的信息,或更改用户会话的设置。session 变量保存的信息是单一用户的,并且可供应用程序中的所有页面使用。

9.1 php session 变量

当运行一个应用程序时,会打开它,做些更改,然后关闭它。这很像一次会话。计算机清楚你是谁。它知道你何时启动应用程序,并在何时终止。但是在因特网上,存在一个问题:服务器不知道你是谁以及你做什么,这是由于 http 地址不能维持状态。

通过在服务器上存储用户信息以便随后使用,php session 解决了这个问题(比如用户名称、购买商品等)。不过,会话信息是临时的,在用户离开网站后将被删除。如果需要永久储存信息,可以把数据存储在中。

session 的工作机制是:为每个访问者创建一个唯一的 id (uid),并基于这个 uid 来存储变量。uid 存储在 cookie 中,亦或通过 url 进行传导。

9.2 开始 php session

在把用户信息存储到 php session 中之前,首先必须启动会话。

注释:session_start() 函数必须位于

标签之前:


上面的代码会向服务器注册用户的会话,以便您可以开始保存用户信息,同时会为用户会话分配一个 uid。

9.3 存储 session 变量

存储和取回 session 变量的正确方法是使用 php $_session 变量:



输出:

pageviews=1

在下面的例子中,我们创建了一个简单的 page-view 计数器。isset() 函数检测是否已设置 "views" 变量。如果已设置 "views" 变量,我们累加计数器。如果 "views" 不存在,则我们创建 "views" 变量,并把它设置为 1:


9.4 终结 session

如果希望删除某些 session 数据,可以使用 unset() 或 session_destroy() 函数。

unset() 函数用于释放指定的 session 变量:

您也可以通过 session_destroy() 函数彻底终结 session:

注释:session_destroy() 将重置 session,您将失去所有已存储的 session 数据。

10、php 发送电子邮件

php 允许您从脚本直接发送电子邮件。

10.1 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 文件中的配置设置进行定义。

10.2 php 简易 e-mail

通过 php 发送电子邮件的最简单的方式是发送一封文本 email。

在下面的例子中,我们首先声明变量($to, $subject, $message, $from, $headers),然后我们在 mail() 函数中使用这些变量来发送了一封 e-mail:

10.3 php mail form

通过 php,能够在自己的站点制作一个反馈表单。下面的例子向指定的 e-mail 地址发送了一条文本消息:


<!--?php
if (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">
  ";
  }
?>

例子解释:

首先,检查是否填写了邮件输入框如果未填写(比如在页面被首次访问时),输出 html 表单如果已填写(在表单被填写后),从表单发送邮件当点击提交按钮后,重新载入页面,显示邮件发送成功的消息

 

11、php 安全的电子邮件

在前面的 php e-mail 脚本中,存在着一个。

11.1 php e-mail 注入

首先,请看前面的 php 代码:


<!--?php
if (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">
  ";
  }
?>

以上代码存在的问题是,未经授权的用户可通过输入表单在邮件头部插入数据。

假如用户在表单中的输入框内加入这些文本,会出现什么情况呢?

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() 函数把上面的文本放入邮件头部,那么现在头部有了额外的 cc:, bcc: 以及 to: 字段。当用户点击提交按钮时,这封 e-mail 会被发送到上面所有的地址!

11.2 php 防止 e-mail 注入

防止 e-mail 注入的最好方法是对输入进行验证。

下面的代码增加了检测表单中 email 字段的输入验证程序:


<!--?php
function spamcheck($field)
  {
  //filter_var() sanitizes the e-mail 
  //address using filter_sanitize_email
  $field=filter_var($field, <code-->filter_sanitize_email);
   
  //filter_var() validates the e-mail
  //address using filter_validate_email
  if(filter_var($field, <code>filter_validate_email</code>))
    {
    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>";
  }
?>

在上面的代码中,我们使用了 php 过滤器来对输入进行验证:

filter_sanitize_email 从字符串中删除电子邮件的非法字符filter_validate_email 验证电子邮件地址

12、php 错误处理

在 php 中,默认的错误处理很简单。一条消息会被发送到浏览器,这条消息带有文件名、行号以及一条描述错误的消息。

12.1 php 错误处理

在创建脚本和 web 应用程序时,错误处理是一个重要的部分。如果代码缺少错误检测编码,那么程序看上去很不专业,也为安全风险敞开了大门。

下面介绍 php 中一些最为重要的错误检测方法。

介绍不同的错误处理方法:

简单的 "die()" 语句 自定义错误和错误触发器错误报告

12.2 基本的错误处理:使用 die() 函数

第一个例子展示了一个打开文本文件的简单脚本:

如果文件不存在,会获得类似这样的错误:

warning: fopen(welcome.txt) [function.fopen]: failed to open stream: 
no such file or directory in c:\webfolder\test.php on line 2

为了避免用户获得类似上面的错误消息,在访问文件之前检测该文件是否存在:

现在,假如文件不存在,会得到类似这样的错误消息:

file not found

比起之前的代码,上面的代码更有效,这是由于它采用了一个简单的错误处理机制在错误之后终止了脚本。

不过,简单地终止脚本并不总是恰当的方式。

12.3 创建自定义错误处理器

创建一个自定义的错误处理器非常简单。简单地创建了一个专用函数,可以在 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 可选。规定一个数组,包含了当错误发生时在用的每个变量以及它们的值。

12.4 错误报告级别

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

 

错误报告级别
常量 描述
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 "error: [$errno] $errstr
";
 echo "ending script";
 die();
 }

上面的代码是一个简单的错误处理函数。当它被触发时,它会取得错误级别和错误消息。然后它会输出错误级别和消息,并终止脚本。

现在,我们已经创建了一个错误处理函数,我们需要确定在何时触发该函数。

12.5 set error handler

php 的默认错误处理程序是内建的错误处理程序。想把上面的函数改造为脚本运行期间的默认错误处理程序。

可以修改错误处理程序,使其仅应用到某些错误,这样脚本就可以不同的方式来处理不同的错误。不过,在本例中,针对所有错误来使用我们的自定义错误处理程序:

set_error_handler("customerror");

由于希望自定义函数来处理所有错误,set_error_handler() 仅需要一个参数,可以添加第二个参数来规定错误级别。

实例

通过尝试输出不存在的变量,来测试这个错误处理程序:

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,将使用自定义错误处理程序并结束脚本:

1)
  {
  throw new exception("value must be 1 or below");
  }
 return true;
 }

//trigger exception
checknum(2);
?>

上面的代码会获得类似这样的一个错误:

fatal error: uncaught exception 'exception' 
with message 'value must be 1 or below' in c:\webfolder\test.php:6 
stack trace: #0 c:\webfolder\test.php(12): 
checknum(28) #1 {main} thrown in c:\webfolder\test.php on line 6

13.3 try, throw 和 catch

要避免上面例子出现的错误,我们需要创建适当的代码来处理异常。

正确的处理程序应当包括:

try - 使用异常的函数应该位于 "try" 代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。throw - 这里规定如何触发异常。每一个 "throw" 必须对应至少一个 "catch"catch - "catch" 代码块会捕获异常,并创建一个包含异常信息的对象

让我们触发一个异常:

1)
  {
  throw new exception("value must be 1 or below");
  }
 return true;
 }

//在 "try" 代码块中触发异常
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 

例子解释:

上面的代码抛出了一个异常,并捕获了它:

创建 checknum() 函数。它检测数字是否大于 1。如果是,则抛出一个异常。在 "try" 代码块中调用 checknum() 函数。checknum() 函数中的异常被抛出"catch" 代码块接收到该异常,并创建一个包含异常信息的对象 ($e)。通过从这个 exception 对象调用 $e->getmessage(),输出来自该异常的错误消息

不过,为了遵循“每个 throw 必须对应一个 catch”的原则,可以设置一个顶层的异常处理器来处理漏掉的错误。

13.4 创建一个自定义的 exception 类

创建自定义的异常处理程序非常简单。简单地创建了一个专门的类,当 php 中发生异常时,可调用其函数。该类必须是 exception 类的一个扩展。

这个自定义的 exception 类继承了 php 的 exception 类的所有属性,您可向其添加自定义的函数。

开始创建 exception 类:

getline().' in '.$this->getfile()
  .': '.$this->getmessage().' 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() 函数。正因为它是旧类的副本,因此它从旧类继承了属性和方法,可以使用 exception 类的方法,比如 getline() 、 getfile() 以及 getmessage()。

例子解释:

上面的代码抛出了一个异常,并通过一个自定义的 exception 类来捕获它:

customexception() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。创建 errormessage() 函数。如果 e-mail 地址不合法,则该函数返回一条错误消息把 $email 变量设置为不合法的 e-mail 地址字符串执行 "try" 代码块,由于 e-mail 地址不合法,因此抛出一个异常"catch" 代码块捕获异常,并显示错误消息

13.5 多个异常

可以为一段脚本使用多个异常,来检测多种情况。

可以使用多个 if..else 代码块,或一个 switch 代码块,或者嵌套多个异常。这些异常能够使用不同的 exception 类,并返回不同的错误消息:

getline().' in '.$this->getfile()
.': '.$this->getmessage().' 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 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。创建 errormessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。执行 "try" 代码块,在第一个条件下,不会抛出异常。由于 e-mail 含有字符串 "example",第二个条件会触发异常。"catch" 代码块会捕获异常,并显示恰当的错误消息

如果没有捕获 customexception,紧紧捕获了 base exception,则在那里处理异常。

13.6 重新抛出异常

有时,当异常被抛出时,希望以不同于标准的方式对它进行处理。可以在一个 "catch" 代码块中再次抛出异常。

脚本应该对用户隐藏系统错误。对程序员来说,系统错误也许很重要,但是用户对它们并不感兴趣。为了让用户更容易使用,您可以再次抛出带有对用户比较友好的消息的异常:

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 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。创建 errormessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。把 $email 变量设置为一个有效的邮件地址,但含有字符串 "example"。"try" 代码块包含另一个 "try" 代码块,这样就可以再次抛出异常。由于 e-mail 包含字符串 "example",因此触发异常。"catch" 捕获到该异常,并重新抛出 "customexception"。捕获到 "customexception",并显示一条错误消息。

如果在其目前的 "try" 代码块中异常没有被捕获,则它将在更高层级上查找 catch 代码块。

13.7 设置顶层异常处理器 (top level exception handler)

set_exception_handler() 函数可设置处理所有未捕获异常的用户定义函数。

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"。

 

14.6 验证输入

验证来自表单的输入。

首先确认是否存在正在查找的输入数据。

然后用 filter_input() 函数过滤输入的数据。

在下面的例子中,输入变量 "email" 被传到 php 页面:

 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.
");
 }
elseif(!$result["email"])
 {
 echo("e-mail is not valid.
");
 }
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 ,或者是规定了过滤器、标志以及选项的数组

14.9 使用 filter callback

通过使用 filter_callback 过滤器,可以调用自定义的函数,把它作为一个过滤器来使用。这样,就拥有了数据过滤的完全控制权。

可以创建自己的自定义函数,也可以使用已有的 php 函数。

规定准备用到过滤器函数的方法,与规定选项的方法相同。

在下面的例子中,使用了一个自定义的函数把所有 "_" 转换为空格:


                    

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网