Composer:自动加载故障排除

时间:2018-01-13 00:07:29

标签: composer-php

我正在提交此问题,因为我一直在搜索有关在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.");
    }
}

我的问题是:

  1. 最可能的罪魁祸首是什么?
  2. 如何使用Composer获取有关其尝试路径的跟踪信息?有没有办法为Composer提供一条路径并让它告诉我它是否可以解决它?

1 个答案:

答案 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')
      );
    }
}