php 特点:
1.php在服务器上运行,结果以纯html文件的形式返回给浏览器
2.php能够应付所产生的一切的需求
cgi协议的出现:
早期的webserver只处理html等静态文件,但是随着技术的发展,出现了像php等动态语言。
webserver处理不了了,怎么办呢?那就交给php解释器来处理吧!
交给php解释器处理很好,但是,php解释器如何与webserver进行通信呢?
为了解决不同的语言解释器(如php、python解释器)与webserver的通信,于是出现了cgi协议。只要你按照cgi协议去编写程序,就能实现语言解释器与webwerver的通信。如php-cgi程序
fast-cgi的出现:
有了cgi协议,解决了php解释器与webserver通信的问题,webserver终于可以处理动态语言了。
但是,webserver每收到一个请求,都会去fork一个cgi进程,请求结束再kill掉这个进程。这样有10000个请求,就需要fork、kill php-cgi进程10000次。
有没有发现很浪费资源?
于是,出现了cgi的改良版本,fast-cgi。fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率。
php-fpm:解析cgi协议的进程管理
php-fpm即php-Fastcgi Process Manager.
php-fpm是 FastCGI 的实现,并提供了进程管理的功能。
进程包含 master 进程和 worker 进程两种进程。
master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。
nginx设置反向代理到 fpm 的9000端口进行解析,然后返回解析好的结果:
配置文件:
server {
listen 80; #监听80端口,接收http请求
server_name www.example.com; #就是网站地址
root /usr/local/etc/nginx/www/huxintong_admin; # 准备存放代码工程的路径
#路由到网站根目录www.example.com时候的处理
location / {
index index.php; #跳转到 www.example.com/index.php
autoindex on;
}
#当请求网站下php文件的时候,反向代理到php-fpm
location ~ \.php$ {
include /usr/local/etc/nginx/fastcgi.conf; #加载nginx的fastcgi模块
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000; #nginx fastcgi进程监听的IP地址和端口
}
}
整个运行机制的文章链接;
运行流程:
php的基本架构:
- Zend引擎:纯C实现,是PHP的内核部分,它将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。
- Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array 系列)、标准库等都是通过extension来实现。
- Sapi :全称是Server Application Programming Interface服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过 sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
常见的一些sapi有:
apache2handler:这是以apache作为webserver,采用mod_PHP模式运行时候的处理方式,也是现在应用最广泛的一种。
cgi:这是webserver和PHP直接的另一种交互方式,也就是大名鼎鼎的fastcgi协议,在最近今年fastcgi+PHP得到越来越多的应用,也是异步webserver所唯一支持的方式。
cli:命令行调用的应用模式 - 上层应用:这就是我们平时编写的PHP程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等
Error 错误的处理:
1.可以利用die(“出现错误的情况来终止程序的继续运行”);
2.创建自定义错误处理器:
error_function( error_level (错误的级别必有参数, 必须是一个数字,下面会详细讲解) ,error_ message(必有参数,用户定义的错误的消息)
下面是非必有参数: error_file : 错误发生的文件名 error_line : 错误发生在哪一行: error_context : 错误发生的上下文(错误发生时所有变量的值);
)
E_NOTICE :错误级别的举例:自定义错误处理函数
<?php
// 错误处理函数
function customError($errno, $errstr)
{
echo "<b>Error:</b> 错误级别: [$errno] 错误信息: $errstr";
}
// 设置错误处理函数
set_error_handler("customError");
// 触发错误
echo($test);
运行结果:
Error: 错误级别: [8] 错误信息: Undefined variable: test
用户如何自定义触发错误 并且 自定义设置触发错误后捕捉到,然后自定义处理:
触发的三种级别:
E_USER_ERROR - 致命的用户生成的 run-time 错误。错误无法恢复。脚本执行被中断。
E_USER_WARNING - 非致命的用户生成的 run-time 警告。脚本执行不被中断。
E_USER_NOTICE - 默认。用户生成的 run-time 通知。在脚本发现可能有错误时发生,但也可能在脚本正常运行时发生
自定义触发以及自定义捕捉:
<?php
// 错误处理函数
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr<br>";
echo "脚本结束";
die();
}
// 设置错误处理函数,并定义了捕捉的错误的级别;
set_error_handler("customError",E_USER_WARNING);
// 触发错误
$test=2;
if ($test>1)
{
trigger_error("变量值必须小于等于 1",E_USER_WARNING);
}
?>
运行结果:
Error: [512] 变量值必须小于等于 1 脚本结束
错误日志的记录:
错误记录
在默认的情况下,根据在 php.ini 中的 error_log 配置,PHP 向服务器的记录系统或文件发送错误记录。通过使用 error_log() 函数,您可以向指定的文件或远程目的地发送错误记录。
通过电子邮件向您自己发送错误消息,是一种获得指定错误的通知的好办法。
合理读取文件的方式:
$filename ="welcome.txt";
if(!file_exists($filename))
{
die("文件不存在");
}
else
{
$file=fopen($filename,r);
// 读取文件每一行,直到文件结尾
while (!feof($file)) {
echo fgets($file) . "<br>";
}
fclose($file);
}
自定义异常 :在自定义异常中书写异常处理方式;
<?php
//todo 自定义异常信息 继承于 基类Exception
class customException extends Exception
{
public function errorMessage()
{
// 错误信息
$errorMsg = '错误行号 '.$this->getLine().' in '.$this->getFile()
.': <b>'.$this->getMessage().'</b> 不是一个合法的 E-Mail 地址';
return $errorMsg;
}
}
$email = "someone@example.com";
try
{
// 检测邮箱
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
{
// 如果是个不合法的邮箱地址,抛出异常
throw new customException($email);
}
echo $email;
} catch (customException $e) {
//display custom message
echo $e->errorMessage();
}
?>
在捕获到异常后重新抛出异常:
<?php
class customException extends Exception
{
public function errorMessage()
{
// 错误信息
$errorMsg = $this->getMessage().' 不是一个合法的 E-Mail 地址。';
return $errorMsg;
}
}
$email = "someone@example.com";
try
{
try
{
// 检测 "example" 是否在邮箱地址中
if(strpos($email, "example") !== FALSE)
{
// 如果是个不合法的邮箱地址,抛出异常
throw new Exception($email);
}
}
catch(Exception $e)
{
// 重新抛出异常
throw new customException($email."jkkkk");
}
}
catch (customException $e)
{
// 显示自定义信息
echo $e->errorMessage();
}
?>
运行结果:
someone@example.comjkkkk 不是一个合法的 E-Mail 地址。
设置公共异常处理函数:
<?php
//todo 设置公共异常处理函数
function myException($exception)
{
echo "<b>Exception:</b> " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
PHP 过滤器?
PHP 过滤器用于验证和过滤来自非安全来源的数据。
Validating 和 Sanitizing
有两种过滤器:
Validating 过滤器:
- 用于验证用户输入
- 严格的格式规则(比如 URL 或 E-Mail 验证)
- 如果成功则返回预期的类型,如果失败则返回 FALSE
Sanitizing 过滤器
- 用于允许或禁止字符串中指定的字符
- 无数据格式规则
- 始终返回字符串
变量过滤器:
filter_var() - 通过一个指定的过滤器来过滤单一的变量
filter_var_array() - 通过相同的或不同的过滤器来过滤多个变量
filter_input - 获取一个输入变量,并对它进行过滤
filter_input_array - 获取多个输入变量,并通过相同的或不同的过滤器对它们进行过滤
<?php
$int = 123;
if(!filter_var($int, FILTER_VALIDATE_INT))
{
echo("不是一个合法的整数");
}
else
{
echo("是个合法的整数");
}
?>
验证一个数是否在0到300中间;
$var=300;
$int_options = array(
"options"=>array
(
"min_range"=>0,
"max_range"=>256
)
);
if(!filter_var($var, FILTER_VALIDATE_INT, $int_options))
{
echo("不是一个合法的整数");
}
else
{
echo("是个合法的整数");
}
?>
对表单输入的字段进行验证
<?php
//todo 验证表单输入是否有email这个字段
if(!filter_has_var(INPUT_GET, "email"))
{
echo("没有 email 参数");
}
else
{
//todo 验证表单输入的这个字段 进行email 格式的验证
if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL))
{
echo "不是一个合法的 E-Mail";
}
else
{
echo "是一个合法的 E-Mail";
}
}
?>
;
对传入的字段进行净化输入:
<?php
if(!filter_has_var(INPUT_GET, "url"))
{
echo("没有 url 参数");
}
else
{
//这个地方是将字段净化为url格式的字段;
$url = filter_input(INPUT_GET, "url", FILTER_SANITIZE_URL);
echo $url;
}
?>
对输入的多个字段使用不同的过滤器进行过滤:
<?php
//todo 预先定义每个变量使用那个过滤器
$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
);
//todo 进行过滤
$result = filter_input_array(INPUT_GET, $filters);
//todo 过滤结果都放入一个result 数组变量中;从数组中取出结果进行判定结果就行;
if (!$result["age"])
{
echo("年龄必须在 1 到 120 之间。<br>");
}
elseif(!$result["email"])
{
echo("E-Mail 不合法<br>");
}
else
{
echo("输入正确");
}
?>
自定义过滤器:
<?php
//todo 自定义的过滤器处理函数
function convertSpace($string)
{
return str_replace("_", ".", $string);
}
$string = "www_runoob_com!";
//todo 使用自定义过滤器进行过滤
echo filter_var($string, FILTER_CALLBACK, array("options"=>"convertSpace"));
?>