movephp / classloader
Movephp框架的扩展自动加载器
Requires
- php: >=7.1
- psr/cache: ~1.0
Requires (Dev)
- phpunit/phpunit: ^6.2
This package is auto-updated.
Last update: 2024-09-25 20:16:20 UTC
README
扩展Autoloader用于Movephp框架
这是一个创建应用程序类映射的机制。它扫描指定的目录以寻找 *.php 文件,并列出所有找到的类(包括抽象类、接口和特性)。对于每个类,也定义了命名空间、父类、使用的接口和特性、子类。
获取到的数据数组可以用于常规的自动加载,也可以用于搜索和分析类映射。
例如,可以找到所有具有指定父类树的类,或者可以找到所有使用特定特性的类等。
这允许快速分析应用程序代码并执行预处理。
目录
安装
推荐安装方式是使用 Composer。请将以下指令添加到您的 composer.json
文件中
"require": {
"movephp/classloader": "~1.0"
}
快速入门
快速入门示例代码
include_once('vendor/autoload.php');
use Movephp\ClassLoader\{Autoload, Map};
$autoload = new Autoload(
new Map\Map()
);
$autoload->setScanPaths(__DIR__ . '/src', __DIR__ . '/vendor');
$autoload->makeMap();
var_dump($autoload->map()->classes());
自动加载器
可以通过 $autoload->register()
方法注册从构建的映射中自动加载类函数。
建议使用缓存(PSR-6)作为类加载库的自动加载器。
$cachePool = new Symfony\Component\Cache\Adapter\FilesystemAdapter();
$autoload = new Autoload(
new Map\Map(),
$cachePool
);
$autoload->setScanPaths(__DIR__ . '/src', __DIR__ . '/vendor');
$autoload->makeMap();
$autoload->register();
使用缓存时,类映射只生成一次,后续请求将快速从缓存中恢复数据。
默认情况下,库使用键
movephp_classloader
从传递的CachePool
获取CacheItem
。为了避免可能的冲突,可以在Autoload
类的构造函数中将命名空间作为第三个参数传递:$autoload = new Autoload($map, $cachePool, 'mynamespace')
- 在这种情况下,用于获取CacheItem
的键将是mynamespace_movephp_classloader
。
更新映射
在开发环境或项目开发中可能需要更新类映射
$cachePool = new Symfony\Component\Cache\Adapter\FilesystemAdapter();
$autoload = new Autoload(
new Map\Map(),
$cachePool
);
$autoload->setScanPaths(__DIR__ . '/src', __DIR__ . '/vendor');
$autoload->makeMap();
if (...some_сondition_here...) {
$autoload->updateMap();
}
$autoload->register();
另一种更慢的方法是完全清除缓存并重新生成映射
$cachePool = new Symfony\Component\Cache\Adapter\FilesystemAdapter();
if (...some_сondition_here...) {
$cachePool->clear();
}
$autoload = new Autoload(
new Map\Map(),
$cachePool
);
$autoload->setScanPaths(__DIR__ . '/src', __DIR__ . '/vendor');
$autoload->makeMap();
$autoload->register();
扫描设置
除了使用 $autoload->setScanPaths()
方法指定应扫描哪些文件/目录外,还存在两个额外的方法
$autoload->setExcludingPaths(string ...$excludePaths)
- 排除指定的文件和目录(以及其所有内容)的扫描过程。对于包含测试的目录来说,使用这个功能是有意义的。$autoload->setOverridePaths(string ...$overridePaths)
- 如果在扫描项目时发现具有相同名称的多个类(包括命名空间),将会引发错误。但是,该方法允许指定包含替换其他扫描文件中同名类的类和目录。在这种情况下不会发生错误,而来自$overridePaths
的类将被添加到映射中。
特殊情况
Composer包
在扫描项目文件时,特别关注 composer.json
文件。如果在找到这样的文件时它包含 autoload
指令,则只会扫描其中描述的目录和文件。
在找到的Composer包中的其他文件将被跳过,因为它们可能只需要用于测试或仅是垃圾。
PHPUnit和Composer库
以下情况下,类不会包含在类映射中,并且既不能用于自动加载也不能用于分析
- 如果类是 phpUnit 测试,即它或其任何一个父类继承自
PHPUnit_Framework_TestCase
或PHPUnit\Framework\TestCase
; - 如果类是 Composer 库的一部分,即它在
Composer
命名空间或其任何子命名空间Composer\...
中定义。
可能存在错误的类
类将被包含在类图中,但在以下情况下不会自动加载:
- 如果类的文件代码中存在
exit()
(或die()
)操作符,且不在类体内,即在文件连接到应用时可能被调用。 - 如果类继承自不在公共类图中的类,或者不是 PHP 的内置类。这也适用于使用的特性和接口。
此类将获得特殊的标记
$item->isSafeInclude() === false
,这意味着加载包含此类的文件可能会导致错误或脚本意外终止。然而,此类将存在于类图中,并可供分析使用。
搜索和分析类
可以通过方法 $autoload->map()
获取形成的类图对象 Map\Map
。如果您不需要自动加载和缓存功能,可以直接使用类 Map\Map
及其方法 scan()
。
$map = new Map\Map();
$map->scan([__DIR__ . '/src', __DIR__ . '/vendor']);
方法 Map\Map::classes()
返回类图中所有类的完整列表,以 Map\Item
对象的数组形式。
使用方法 Map\Map::find()
可以在类图中根据指定参数进行搜索。以下是一个搜索实现 MyNamespace\MyInterface
接口且不是抽象类的示例,以及这些类的子类。
$map->find(Map\Item::TYPE_CLASS, MyNamespace\MyInterface::class);
方法 find()
也返回 Map\Item
对象的数组。
Map\Item
对象(类图元素)具有许多用于获取关于所代表类各种信息的属性访问器方法。
API参考
Movephp\ClassLoader\Autoload
这是库的主要类。用于根据类图执行自动加载器功能,以及管理类图对象和其缓存。
构造函数
__construct(Movephp\ClassLoader\Map\MapInterface $cleanMap, Psr\Cache\CacheItemPoolInterface $cachePool = null, string $cacheKeyNamespace = '')
方法
Movephp\ClassLoader\Map\Map
此类的对象代表类图,用于其构建(扫描项目文件)和搜索。
构造函数
__construct(string $itemClass = '')
方法
方法 find()
参数 $type
的可能值:
Movephp\ClassLoader\Map\ItemInterface::TYPE_CLASS
Movephp\ClassLoader\Map\ItemInterface::TYPE_ABSTRACT
Movephp\ClassLoader\Map\ItemInterface::TYPE_INTERFACE
Movephp\ClassLoader\Map\ItemInterface::TYPE_TRAIT
- 或者这些常数的任何组合(
Movephp\ClassLoader\Map\ItemInterface::TYPE_ANY
是它们的总和)。
Movephp\ClassLoader\Map\Item
此类的对象代表类图中的一个元素:在扫描过程中找到的类、接口或特性。
方法
待办事项
- 使在指定扫描和排除扫描的目录和文件时使用特殊符号
*
和?
成为可能; - 配置扫描文件的扩展名(默认为
*.php
); - 避免直接调用文件系统函数(使用
Flysystem
或类似库)。