常用的回调注册函数有:

set_error_handler:如果你想在程序发生缺点时想做点什么处理就用这个

set_exception_handler:如果你想在程序发生非常时想做点什么处理就用这个

php回调函数PHP常用的体系回调 Angular

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,由于程序结束回调函数是可以注册多个的

其余就算中途实行exitdie也会触发这个回调

运用处景:当程序结束后,如果判断出是调试模式,会进行内存利用情形和运行韶光的统计;其余如果通过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