nastuzzi-samy / reflection-namespace
反射命名空间,给出其类、子命名空间等更多内容
Requires (Dev)
- phpmd/phpmd: ^2.6
- phpstan/phpstan: ^0.10.5
- phpunit/phpunit: ^7.5
- squizlabs/php_codesniffer: ^3.3
This package is auto-updated.
Last update: 2024-09-26 07:20:30 UTC
README
简介
为什么不能使用特定目录下的根命名空间来搜索所有类和子目录,而要搜索所有类和子目录?
此外,有时同一命名空间下的文件定义在不同的目录中,需要多次研究才能获取所有这些文件。
PHP 默认有多个 Reflector
类:类、参数、常量、方法等。但不存在反射命名空间的方法。现在,由于所有项目都通过 Composer 使用不同的包,这可能很有用。
ReflectionNamespace
类从 Composer 加载数据(子命名空间、类)。它使用 PSR-0(默认禁用)、PSR-4、classmap 和文件自动加载器。它还从已声明的类、特质和接口(也默认禁用)加载。
安装
通过 Composer 简单安装
composer install nastuzzi-samy/reflection-namespace
由于其与 Composer 引擎(自动加载器)协同工作,因此需要在 Composer 项目中实现。
用法
首先,ReflectionNamespace
类与其他 Reflector
类一样位于根命名空间。
Project example structure:
app/
Http/
Controller.php
Models/
User.php
vendor/
...
random-package/ # RandomPackage defines app/ as \App namespace also
app/
Console/
Models/
Group.php
创建
要创建一个新的 ReflectionNamespace
,您需要将其作为字符串传递给它要工作的命名空间
<?php // Regroup the namespace generated by our projet and the RandomPackage package: new \ReflectionNamespace('App'); new \ReflectionNamespace('App\\'); // It is the same that the previous one. new \ReflectionNamespace('\\App\\'); // Same. new \ReflectionNamespace('\\App'); // Same. // Regroup the namespace generated by our RandomPackage package: new \ReflectionNamespace('App\Console'); new \ReflectionNamespace('App\Console\\'); // It is the same that the previous one. new \ReflectionNamespace('\\App\Console'); // Same. new \ReflectionNamespace('\\App\Console\\'); // Same. ?>
获取信息
由于其开销很大,ReflectionNamespace
只在请求时加载类和命名空间。主要来说,您可以使用该类仅解析命名空间的短名和长名,而不必担心资源消耗。
<?php $modelsReflection = new \ReflectionNamespace('App\\Models'); echo $modelsReflection->getName(); // App\Models echo $modelsReflection->getShortName(); // Models echo $modelsReflection->getParentName(); // App ?>
获取类和命名空间
通过获取类或命名空间,ReflectionNamespace
类将加载所有数据,遍历所有 Composer 自动加载器,在某些情况下,如果 Composer 没有缓存所有文件/类,则搜索目录(仅限于 PSR-0 和 PSR-4)。
<?php $modelsReflection = new \ReflectionNamespace('App\\Models'); // Equivalent to: new \ReflectionNamespace('App'); $appReflection = $modelsReflection->getParent(); /* Get all class names under App\Models. Equivalent to: [ 'User' => 'App\\Models\\User', 'Group' => 'App\\Models\\Group', ]; */ $modelsReflection->getClassNames(); /* Get all classes under App\Models. Equivalent to: [ 'User' => new \ReflectionClass('App\\Models\\User'), 'Group' => new \ReflectionClass('App\\Models\\Group'), ]; */ $modelsReflection->getClasses(); /* Get all namespace full names under App. Equivalent to: [ 'Console' => 'App\\Console', 'Http' => 'App\\Http', 'Models' => 'App\\Models', ]; */ $appReflection->getNamespaceNames(); /* Get all namespaces under App. Equivalent to: [ 'Console' => new \ReflectionNamespace('App\\Console'), 'Http' => new \ReflectionNamespace('App\\Http'), 'Models' => new \ReflectionNamespace('App\\Models'), ]; */ $appReflection->getNamespaces(); ?>
当然,您可以使用 getClass
和 getNamespace
获取精确的类或命名空间。或者,您可以使用 hasClass
和 hasNamespace
检查命名空间是否拥有类或子命名空间。
<?php // Equivalent to: new \ReflectionClass('App\\Models\\User'); $modelsReflection->getClass('User'); // Throw an exception. $modelsReflection->getClass('NoModel'); echo $appReflection->hasNamespace('Models'); // TRUE echo $modelsReflection->hasNamespace('User'); // FALSE ?>
高级用法
启用 PSR-0 加载
默认情况下,PSR-0 加载器不处理(因为它已被弃用),反射可能会导致不完整搜索。为此,要使用 PSR-0 加载器,您可以通过调用静态方法启用其使用
<?php // Ask the class to load also from PSR-0. \ReflectionNamespace::loadPRS0(TRUE); // Refresh all loaded data: $modelsReflection->reload(); $appReflection->reload(); // Ask the class not to load from PSR-0. \ReflectionNamespace::loadPRS0(FALSE); ?>
启用从已加载的类、接口和特质加载
默认情况下,不处理加载所有已声明的类、接口和特质,反射可能会导致不完整搜索。这是因为在大型项目中,使用大量重型包可能会非常昂贵。由于其很少使用,通常由 Composer 列出所有已声明的类。由于任何原因,如果想要加载所有这些,可以通过调用静态方法启用其使用
<?php // Ask the class to load also from loaded classes, interfaces and traits. \ReflectionNamespace::loadDeclaredClasses(TRUE); // Refresh all loaded data: $modelsReflection->reload(); $appReflection->reload(); // Ask the class not to load from loaded classes, interfaces and traits. \ReflectionNamespace::loadDeclaredClasses(FALSE); ?>
操作加载器
您可以使用静态方法 getLoaders
获取基本加载器。加载器对所有 ReflectionNamespace
对象都是通用的。
如测试代码 tests/0-DefinitionTest.php
中所述,您可以在任何时候创建自己的自动加载器。重要的是要请求类重新加载所有加载器,并重新加载每个对象以使用完整的加载器列表
<?php // Ask to reload all loaders: \ReflectionNamespace::getLoaders(TRUE); // Refresh all loaded data to use the full loader list: $modelsReflection->reload(); $appReflection->reload(); ?>
如果加载器只会影响一个对象,您还可以要求ReflectionNamespace
对象从新的加载器中加载。
<?php $myNewLoader = new \Composer\Autoload\ClassLoader(); /* work on $myNewLoader... */ $appReflection->fillWithLoader($myNewLoader); ?>
您还可以填充一个简单的类映射。
<?php $modelsReflection->fillWithClassMap([ 'App\\Models\\Article', 'App\\Models\\Comment', ]); ?>
扩展类。
当然,类是可扩展的。所有方法和属性都是受保护的,以便您可以在子类中编辑它们。
请务必在使用前充分理解其工作原理。
贡献
报告错误
如果您遇到奇怪的行为,某些类未检测到,命名空间缺失,检测到异常?请打开一个包含尽可能多信息的工单,让我们帮助您 :)。
开发
首先,在您的组织中分叉项目。完成后,显然您需要克隆您的仓库。
克隆后,您需要通过运行以下命令准备所有未来的测试:composer prepare-test
。
进行您的修改,在推送和打开PR之前,运行此命令并确保它工作良好:composer test
。
当然,如果您添加功能或代码,或简单地修复一个显著的错误,您需要编写测试 :)。
提前感谢您的贡献 ;)
捐赠
因为它花费了我时间,而且我仍然是一个需要咖啡的简单学生,请不要犹豫在此捐赠,这将是我工作的荣幸和认可 :)。