若提供了 PSR-0 和 PSR-4 标准,要加载一个类通常是很容易的事。得益于Symfony的ClassLoader组件,以及Composer的自动加载架构,你毋须手动映射你的类名称到其真实文件上。如今,PHP类库普遍都能通过Composer实现对自动加载的支持。
但是你仍然有可能用到“不支持任何自动加载”的第三方类库,并因此迫使你手动加载每一个类。例如,设想一个拥有如下目录结构的类库:
1
2
3
4
5
6
7
8
9library/
├── bar/
│ ├── baz/
│ │ └── Boo.php
│ └── Foo.php
└── foo/
├── bar/
│ └── Foo.php
└── Bar.php
这些文件包含以下的类:
File(文件)
Class Name(类名)
library/bar/baz/Boo.php
Acme\Bar\Baz
library/bar/Foo.php
Acme\Bar
library/foo/bar/Foo.php
Acme\Foo\Bar
library/foo/Bar.php
Acme\Foo
为了令你坦然面对,ClassLoader组件内置了
生成类映射 ¶
要生成类映射,只需把你的类文件所在的根目录传入
1
2
3use Symfony\Component\ClassLoader\ClassMapGenerator;
var_dump(ClassMapGenerator::createMap(__DIR__.'/library'));
根据上表中给定的文件和类,你应该能看到如下的输出:
1
2
3
4
5
6
7Array
(
[Acme\Foo] => /var/www/library/foo/Bar.php
[Acme\Foo\Bar] => /var/www/library/foo/bar/Foo.php
[Acme\Bar\Baz] => /var/www/library/bar/baz/Boo.php
[Acme\Bar] => /var/www/library/bar/Foo.php
)
剥离类映射 ¶
要使用自动加载,光把类映射(class map)输出到命令行是不够的。好在, ClassMapGenerator 提供的
1
2
3use Symfony\Component\ClassLoader\ClassMapGenerator;
ClassMapGenerator::dump(__DIR__.'/library', __DIR__.'/class_map.php');
这个 dump() 调用,生成类映射并后将其写入相同目录下的 class_map.php 文件,文件内容如下:
1
2
3
4
5
6
'Acme\\Foo' => '/var/www/library/foo/Bar.php',
'Acme\\Foo\\Bar' => '/var/www/library/foo/bar/Foo.php',
'Acme\\Bar\\Baz' => '/var/www/library/bar/baz/Boo.php',
'Acme\\Bar' => '/var/www/library/bar/Foo.php',
);
不同于每次手动加载文件,你要做的只是把已生成的类映射,注册到
1
2
3
4
5
6
7
8
9
10
11
12use Symfony\Component\ClassLoader\MapClassLoader;
$mapping = include __DIR__.'/class_map.php';
$loader = new MapClassLoader($mapping);
$loader->register();
// you can now use the classes: / 现在你可以使用类了
use Acme\Foo;
$foo = new Foo();
// ...
本例假设你的自动加载已经可以使用(比如通过 Composer 或来自ClassLoader组件的其他加载器)。
除了在一个目录中剥离出类映射,你还可以传入一个目录数组,用于生成类映射(结果完全与上例是一样的):
1
2
3
4
5
6use Symfony\Component\ClassLoader\ClassMapGenerator;
ClassMapGenerator::dump(
array(__DIR__.'/library/bar', __DIR__.'/library/foo'),
__DIR__.'/class_map.php'
);