我正在提交此问题,因为我一直在搜索有关在Composer中自动加载问题的主题,但似乎找不到任何简单明了的内容。我在库中添加了几个类,然后在项目中引用它们。该项目找不到类。以下是相关事实:
•我已经在项目中使用该库一段时间了。
•我仔细检查了库中类的代码文件中的名称空间声明:
namespace \Library\Package\Subpackage;
class Widget { ...
•我仔细检查了为库和实例化别名的use
语句:
use \Library\Package\Subpackage as Subpackage;
$e = new Subpackage\Widget();
•对于笑脸,我改变了别名:
use \Library\Package\Subpackage\Widget as Widget;
$e = new Widget();
•对于更多的笑容,我尝试了直接参考:
$e = new \Library\Package\Subpackage\Widget();
•我还确保composer update
并确保文件实际存在,位于正确的路径:
composer update
find . -name Widget.php
./vendor/organization/library/Package/Subpackage/Widget.php
•作为完整性检查,我在同一个库中添加了对另一个项目的引用,但是在不同的子包中。
$f = new \Library\Package2\Widget2(); // this works fine
•作为绝对的最后手段,我将引用放在一个PHP文件中,然后运行它。
require_once __DIR__.'/vendor/autoload.php';
$e = new \Library\Package\Subpackage\Widget();
•对于 coup de grace ,我编写了一个单元测试,用于检查库vendor
文件夹中的每个文件:
class AutoloadTest extends \PHPUnit\Framework\TestCase
{
public function classDataProvider()
{
$data = array();
$path = realpath('organization/library/Package/');
$directory_iterator = new \RecursiveDirectoryIterator($path);
$iterator_iterator = new \RecursiveIteratorIterator($directory_iterator);
foreach ($iterator_iterator as $iterator_result) {
$real_path = $iterator_result->getRealPath();
if (substr($real_path, -4, 4) != '.php') {
continue;
}
$split = explode('organization/library/Package/', $real_path);
$processed_path = substr($split[1], 0, -4);
$class_fqname = sprintf('\Library\%s', str_replace("/", '\\', $processed_path));
$data[] = array($class_fqname);
}
return $data;
}
public function test($class_name)
{
$assertion = class_exists($class_name) || trait_exists($class_name) || interface_exists($class_name);
$this->assertTrue($assertion, "$class_name is not recognized as a class, trait or interface.");
}
}
我的问题是:
答案 0 :(得分:0)
无关的反斜杠。
namespace \Library\Package\Subpackage;
^ oops!
删除此反斜杠解决了这个问题。
最终,我写的单元测试帮助我找到并解决了问题。因此,对于我的问题的第二部分,我提供了我写的测试类。提供程序接收扫描路径对和文件所属的命名空间。它扫描给定的路径并查找该命名空间中的类。测试检查断言每个限定类名称对应于类,特征或接口。 (当然,需要自动加载器来加载类。)
abstract class AutoloadTestBase extends \PHPUnit\Framework\TestCase
{
public function pathProvider()
{
$data = array();
foreach ($this->directories() as $directory_specification) {
list($path, $namespace) = $directory_specification;
if (empty($path)) {
continue;
}
$directory_iterator = new \RecursiveDirectoryIterator($path);
$iterator_iterator = new \RecursiveIteratorIterator($directory_iterator);
foreach ($iterator_iterator as $iterator_result) {
$real_path = $iterator_result->getRealPath();
$split1 = explode($path.'/', $real_path);
if (count($split1) < 2) {
continue;
}
$success = preg_match('/^(.+)\.php$/', $split1[1], $split2);
if (!$success || substr($split2[1], 0, 5) == 'Tests') {
continue;
}
$class_fqname = sprintf('%s\%s', $namespace, str_replace("/", '\\', $split2[1]));
$data[] = array($class_fqname);
}
}
return $data;
}
/**
* @dataProvider pathProvider
*/
public function test($class_name)
{
$assertion = class_exists($class_name) || trait_exists($class_name) || interface_exists($class_name);
$this->assertTrue($assertion, "$class_name is not recognized as a class, trait or interface.");
}
}
class AutoloadTest extends AutoloadTestBase
{
protected function directories()
{
return array(
array('Package1/Subpackage1','\Library1\Package1\Subpackage1'),
array('vendor/organization2/package2/Subpackage2','\Library2\Package2\Subpackage2')
);
}
}