我遇到Codeception/AspectMock的问题。 当使用自定义自动加载器并尝试创建一个类的实例,该类具有相同的自定义命名空间的父类时,我有这样的错误:
PHP致命错误:未捕获InvalidArgumentException:类[parent 定位器未找到类名] 供应商/ goaop /解析器反射/ SRC / ReflectionEngine.php:112
我的设置非常简单:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$kernel = AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__. '/lib'],
]);
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
$b = new \lib\B();
Class \ lib \ B:
namespace lib;
class B extends A {}
Class \ lib \ A:
namespace lib;
class A
{
public function getName()
{
return static::class;
}
}
通过我的自定义自动加载器加载B类,但是定位器尝试通过composer autoloader加载父类A并返回此错误。这是一个错误,还是我做错了什么?
答案 0 :(得分:4)
主题入门者已经获得答案on GitHub。
要使用自定义自动加载器,您应该使用复合类定位器重新初始化ReflectionEngine,该复合类定位器将能够找到您的类,或者您可以将CallableLocator与闭包一起使用来解析路径。
或者,甚至更好的是,您可以将代码库切换到PSR0 / PSR-4
例如:
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
\Go\ParserReflection\ReflectionEngine::init(
new class implements \Go\ParserReflection\LocatorInterface {
public function locateClass($className) {
return (new ReflectionClass($className))->getFileName();
}
}
);
$b = new \lib\B(); // here you go
答案 1 :(得分:1)
如果您可以轻松地在代码库上进行查找和替换,也许您可以将代码重构为PSR-4自动加载标准,而完全不需要自定义自动加载器。
这是规范https://www.php-fig.org/psr/psr-4/。我将尽力解释它。
想象一下将小写的命名空间objects_to_remove <- c("age", "another_object") # etc
rm(list = objects_to_remove)
更改为lib
,并将该命名空间设置为Lib
中的src/
目录:
composer.json
设置后,运行"autoload": {
"psr-4": {
"Lib\\": "src/"
}
}
。然后,您要做的就是搜索并替换composer dumpautoload
,并替换为namespace lib;
。
位于namespace Lib;
中的示例类的顶部应该是src/Form.php
,然后是namespace Lib;
。
class Form
命名空间使用文件夹命名约定。直接在<?php
namepace Lib;
class Form
{
// code
}
中的所有类都具有命名空间src/
。如果存在子目录,则目录名称将成为名称空间的一部分。例如,Lib;
中的文件将具有src/Form/Field/Text.php
。
namespace Lib\Form\Field; class Text {}
您可以在上面的链接中看到完整的约定,但一般规则是使所有文件夹都以大写字母开头,例如您的类名,并且自动加载器应能够找到所有类。
这可能是您的最佳实践解决方案,就像我说的那样,只需要一点文件重命名和名称空间调整即可。祝你好运!