【问题标题】:PHP Class not found from a different namespace未从不同的命名空间中找到 PHP 类
【发布时间】:2014-02-17 04:19:29
【问题描述】:

我目前正在使用 Phpspec 进行 Symfony2 项目,但在扩展不同命名空间中描述的 Spec 类时遇到问题。

例如,在我的项目中,spec/Acme/Model/Foo/FooSpec.php 中描述了以下类:

namespace spec\Acme\Model\Foo;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

abstract class FooSpec extends ObjectBehavior{
    //some code here
}

我在spec/Acme/Model/Bar/BarSpec.php 中还有一个类扩展FooSpec

namespace spec\Acme\Model\Bar;

use spec\Acme\Model\Foo\FooSpec;

class BarSpec extends FooSpec{
    //some code here
}

当我尝试运行 phpspec 时,出现以下错误:

PHP Fatal error: Class 'spec\Acme\Model\Foo\FooSpec' not found in /home/user/Projects/Acme/spec/Acme/Model/Bar/BarSpec.php on line 9

我发现使它工作的唯一方法是在spec/Acme/Model/Bar/BarSpec.php 中添加以下行:

include('./spec/Acme/Model/Foo/FooSpec.php');

我不知道为什么我必须包含这个特定文件才能使其运行,尤其是在正确找到其他类(如 PhpSpec\ObjectBehavior)时。

你知道为什么会这样吗?


编辑:

正如 @Phil 和 @Sheikh Heera 在 cmets 中所建议的那样,我尝试设置一个 autoload 来注册我的规范命名空间,但它也不起作用。这是我到目前为止所尝试的:

require_once getcwd() . '/vendor/composer/ClassLoader.php';

$loader = new \Composer\Autoload\ClassLoader();

// register classes with namespaces
$loader->add('spec', getcwd().'/spec');

// activate the autoloader
$loader->register();

我也尝试修改文件vendor/composer/autoload_namespaces.php 来添加这个:

return array(
    //some code here

    'spec' => array(getcwd() . '/spec'),
    //some more code

);

但仍然是同样的错误。我还尝试使用'spec' => array(getcwd())$loader->add('spec', getcwd()); 只是为了看看会发生什么,这次我在另一个规范类上得到了Cannot redeclare class


我的php版本是PHP 5.4.9-4ubuntu2.4 (cli)

提前感谢您的帮助。

【问题讨论】:

  • 您是否为 PHPSpec 知道的 spec 命名空间设置了自动加载器?
  • Check this,它可能会有所帮助。
  • @SheikhHeera 和 Phil,我更新了我的问题
  • 我相信这是因为 PHPSpec 的创建者并不打算让您的测试扩展其他测试。你为什么要这样做?
  • @CarlOwens,我这样做是因为我有一个抽象类,它被其他 3 个类继承(目前)。我不想在每个孩子中复制粘贴抽象类的规范,但我想确保这 ​​3 个孩子具有相同的行为。因此,我想让它们扩展抽象类。你可以看看这个讨论:PhpSpec - Issue #54Marijn 做的和我想做的一样。

标签: php symfony classnotfound phpspec


【解决方案1】:

更通用的解决方案是将 spec 目录放入 composer.json 的 autoload-dev 配置中:

"autoload-dev": {
    "psr-0": {
        "spec\\":""
    }
},

这样,composer 也会为规范生成命名空间,该命名空间应该位于存储库的根目录中:

return array(
     'spec\\' => array($baseDir . '/'),
     ...
);

【讨论】:

  • 我最终使用了这个解决方案,但忘记更新我的答案。我接受了您的回答,以便其他人可以看到。谢谢
【解决方案2】:

最后,正如 Phil 和 Sheikh Heera 在 cmets 中所建议的那样,我实际上为“解决”我的“问题”所做的是自动加载我的命名空间,以便它被规范识别。

这是我为使它工作所做的:

  • 我在 `vendor/composer/autoload_namespaces.php` 文件中添加了以下行:
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
    //some code
    'spec\\Acme\\Behavior' => array(getcwd()),
    //some code
);
  • 然后我创建了以下文件夹结构:
│── 规格 │  └── Acme │ └── 行为 │ └── FooBehavior.php
  • 我以这种方式在 `spec/Acme/Behavior/FooBehavior.php` 中声明了命名空间:
namespace spec\Acme\Behavior;
  • 并在 `spec/Acme/Model/Bar/BarSpec.php` 中使用如下:
use spec\Acme\Behavior\FooBehavior;

class BarSpec extends FooBehavior{
    //...
}

我知道这不是最佳做法,因为每次有人从事这个项目时,第一步都必须手动重现。因此,如果您有更好的想法,请随时发表评论或发布答案。

【讨论】:

    猜你喜欢
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 2013-11-11
    • 2017-05-01
    相关资源
    最近更新 更多