昨天面试被问到了 PHP 的自动加载机制,因为很多概念模糊啦,没回答好,今天特意来总结一下。
include 和 require 是PHP中引入文件的两个基本方法,但是每个脚本的开头,都需要包含(include)一个长长的列表总是不好的,所以 PHP 使用了自动加载器来解决这个问题。
功能:就是把传入的参数(可以为回调函数或函数名称)注册到 SPL __autoload 函数队列中。如果在你的程序中已经实现了 __autoload 函数,它必须显式注册到队列中。(PHP 5 >= 5.1.0, PHP 7)
参数介绍:
autoload_function
无法成功注册时, spl_autoload_register()是否抛出异常。 1 <?php
2 namespace Foobar;
3
4 class Foo {
5 static public function test($name) {
6 print '[['. $name .']]';
7 }
8 }
9 spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // 自 PHP 5.3.0 起
10
11 new InexistentClass;
12
13 ?>
输出示例:
上述代码:将 Foo 的静态方法 test 注册到自动加载队列中,通过上面的示例可以看到 自动加载的运行过程,既:当需要使用的类没有被引入时,这个函数会在PHP报错前被触发。
函数里面的具体逻辑要根据我们的具体情况实现,就上面的问题而言,引入的函数需要同样在 Foobar 的命名空间之下,并且声明 InexistentClass 对象。(PSR-4 是关于由文件路径自动载入对应类的相关规范)。
为类名称使用别名、为接口使用别名或为命名空间名称使用别名。PHP 5.6开始允许导入函数或常量或者为它们设置别名。
PHP 7 可以使用一个 use 从同一个 namespace 中导入类、函数和常量。
1 // PHP 7 之前版本需要使用多次 use
2 use some\namespace\ClassA;
3 use some\namespace\ClassB;
4 use some\namespace\ClassC as C;
5
6 use function some\namespace\fn_a;
7 use function some\namespace\fn_b;
8 use function some\namespace\fn_c;
9
10 use const some\namespace\ConstA;
11 use const some\namespace\ConstB;
12 use const some\namespace\ConstC;
13
14 // PHP 7+ 之后版本可以使用一个 use 导入同一个 namespace 的类
15 use some\namespace\{ClassA, ClassB, ClassC as C};
16 use function some\namespace\{fn_a, fn_b, fn_c};
17 use const some\namespace\{ConstA, ConstB, ConstC};
18 ?>
use 关键字并不是立刻导入所 use 的类,它只是声明某类的完整类名(命名空间::类标示符),而后你在上下文中使用此类时系统才会根据 use 声明获取此类的完整类名 然后利用自动加载机制进行载入。
1 <?php
2 use \Psr\Http\Message\ServerRequestInterface as Request;
3 use \Psr\Http\Message\ResponseInterface as Response;
4 require 'vendor/autoload.php';
5
6 $app = new \Slim\App;
7 $app->get('/hello/{name}', function (Request $request, Response $response) {
8 $name = $request->getAttribute('name');
9 $response->getBody()->write("Hello, $name");
10 return $response;
11 });
12 $app->run();
就像如上的代码 自动载入函数是在 use 两个类之后方才实现的 因为 use 并不会立即使用此类 只有在你调用此类时系统才会在找不到此类的情况下通过 autoload 函数动态延迟加载,若仍加载不到,则报错。