常用的回调注册函数有:
set_error_handler
:如果你想在程序发生缺点时想做点什么处理就用这个
set_exception_handler
:如果你想在程序发生非常时想做点什么处理就用这个
register_shutdown_function
:当程序结束时想做点什么处理就用这个
spl_autoload_register
:当调用一个不存在的类时自动加载这个类就用这个
__autoload
:(旧版,不推举)当调用一个不存在的类时自动加载这个类就用这个
下面逐一讲授(下面附加的测试代码直接复制粘贴到单独脚本就可以运行测试,不须要依赖任何其它东西)
set_error_handler
设置缺点的处理函数
函数原型:mixed set_error_handler(callable $error_handler [, int $error_types = E_ALL | E_STRICT ])
测试代码:
set_error_handler(function($code, $message, $file, $line){
echo <<<EOL
缺点类型特色码:$code<br/>
缺点:$message<br/><br/>
出错文件:$file<br/>
出错行号:$line
EOL;
});
error_reporting(-1); //只是为了担保会报错,以防php.ini配置屏蔽了下面的缺点
$a = [];
echo $a[5];
用网页运行就会看到这样的报错:
缺点代码:8
缺点:Undefined offset: 5
出错文件:D:\phpStudy\www\test\index.php
出错行号:14
正是由于咱们通过set_error_handler设置了自定义的缺点处理才有这样的输出
如果不set_error_handler的话,出错的时候会利用PHP自带的默认处理,输出内容大概是这样的:
Notice: Uninitialized string offset: 5 in D:\phpStudy\www\test\index.php on line 14
运用处景:出了错就会引发这个回调函数的实行,然而程序出错当然是程序员不肯望涌现的,既然出错了我们就希望只管即便知道是什么缺点,以是常日在这个时候做日志记录或者发邮件关照等都可能会涌现
set_exception_handler
设置非常的处理函数
函数原型:callable set_exception_handler(callable $exception_handler )
调用思路和set_error_handler一样测试代码:
set_exception_handler(function($exception){
$code = $exception->getCode();
$message = $exception->getMessage();
$file = $exception->getFile();
$line = $exception->getLine();
echo <<<EOL
非常类型特色码:$code<br/>
非常:$message<br/><br/>
抛出非常的文件:$file<br/>
抛出非常的行号:$line
EOL;
});
error_reporting(-1);
throw new Exception('测试非常');
则输出:
缺点类型特色码:0
缺点:测试非常
出错文件:D:\phpStudy\www\test\index.php
出错行号:19
运用处景:跟set_error_handler一样
register_shutdown_function
注册程序结束时的回调函数
函数原型:void register_shutdown_function( callable $callback [, mixed $parameter [, mixed $... ]] )
测试代码:
register_shutdown_function(function(){
echo '<br/>程序运行结束1,本次运行一共耗费内存:' . memory_get_peak_usage(true) . '字节';
});
register_shutdown_function(function(){
echo '<br/>程序运行结束2,本次运行一共耗费内存:' . memory_get_peak_usage(true) . '字节';
});
$random = mt_rand(99, 999);
$result = [];
for($i = 0; $i < $random; $i++){
$result[] = array_fill(0, $i, $i);
}
echo '一共创建了' . count($result) . '个数组';
输出:
一共创建了749个数组
程序运行结束1,本次运行一共耗费内存:15466496字节
程序运行结束2,本次运行一共耗费内存:15466496字节
上面的测试代码实行了两次register_shutdown_function,由于程序结束回调函数是可以注册多个的
其余就算中途实行exit
或die
也会触发这个回调
运用处景:当程序结束后,如果判断出是调试模式,会进行内存利用情形和运行韶光的统计;其余如果通过error_get_last
函数获取到缺点的话会进行日志记录,让程序员知道去修复
spl_autoload_register
注册自动加载函数
函数原型:bool spl_autoload_register([callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]])
测试代码:
spl_autoload_register(function($className){
echo '代码加载了不存在的类:' . $className . '<br/>';
if(!class_exists($className, false)){
echo '经确认' . $className . ' 这个类确实是不存在的<br/>';
}
//创建这个类,实际运用中文件已经存在,我现在是动态创建文件
$classCode = <<<EOL
class $className{
public function test(){
echo 'hi,我是' . __CLASS__ . '<br/><br/><br/>';
}
}
EOL;
file_put_contents($className . '.php', $classCode);
include($className . '.php');
if(class_exists($className, false)){
echo '好了,' . $className . ' 这个类存在了<br/>';
}else{
return false; //如果加载不到类请返回false让系统自动调用下一个autoload回调
}
return new $className();
});
$a = new A();
$a->test();
$b = new B();
$b->test();
$c = new C();
$c->test();
输出结果:
代码加载了不存在的类:A
经确认A 这个类确实是不存在的
好了,A 这个类存在了
hi,我是A
代码加载了不存在的类:B
经确认B 这个类确实是不存在的
好了,B 这个类存在了
hi,我是B
代码加载了不存在的类:C
经确认C 这个类确实是不存在的
好了,C 这个类存在了
hi,我是C
并且和register_shutdown_function
一样,spl_autoload_register
可以注册多个自动加载函数,虽然很少见,但是偶尔还是有的
比如有两种情形是用spl_autoload_register注册多个自动加载函数的:
重构一个项目
项目的代码比较老,用spl_autoload_register注册过他们自己的加载逻辑,但重构时须要一部分一部分重构,以是要基于旧代码改,此时再通过spl_autoload_register添加了新的加载逻辑,在加载新的类时,旧的加载代码是找不到文件的,于是就靠新注册的加载函数去加载了,两个加载函数会被轮流调用
双框架项目
精良的框架在本地化方面是做得很精良的,基本没有全局变量和常量,以是有些分外情形下会须要在A框架做的项眼前引入B框架,利用B框架做它善于的事,比如Codeception框架整合了Gazzle框架做Http处理
而我自己做的项目也经历过双框架,乃至三框架模式
运用处景:项目的类自动加载,现在已经越来越少人手动include一个类文件再new一个类了,都是直接new,不存在的时候就自动加载,并且加载逻辑方面开始有了PHP行业的统一规范:PSR4规范 自动载入类
__autoload
自动加载不存在的类
函数原型:void __autoload(string $class)
这个在PHP5.1.2往后就被spl_autoload_register
取代了,以是不建议利用的,然而我为什么还要讲这个函数呢
实在由于大部分现存的PHP程序还是基于兼容旧版的设计的,以是在自动加载方面可能会有部分程序利用了__autoload
而不该用spl_autoload_register
测试代码:
//直接声明这个函数就可以
function __autoload($className){
file_put_contents($className . '.php', \公众 class $className{ public function test(){ echo 'hi wo shi A'; } }\"大众);
return new $className();
}
$a = new A();
echo $a->test();
结果输出:
hi wo shi A