【问题标题】:Name already in use fatal error using composer's autoload in PHPUnit名称已在使用中使用 PHPUnit 中作曲家的自动加载的致命错误
【发布时间】:2015-12-31 21:59:52
【问题描述】:

在 Composer 中使用 PSR-4 自动加载,当我尝试测试此类时:

namespace User;

use User\Contracts\UserId;
use User\Contracts\User as UserContract;

class User implements UserContract
{
    private $id;

    public function __construct(UserId $id)
    {
        $this->id = $id;
    }

    public function getId()
    {
        return $this->id;
    }
}

使用 PHPUnit:

use User\Contracts\UserId;

class UserTest extends \PHPUnit_Framework_TestCase
{
    public function test_the_identifier_can_be_used_as_string()
    {
        $identifier = m::mock(UserId::class);
        $identifier->shouldReceive('__toString')->once()->andReturn('foo');

        $user = new User($identifier);

        $this->assertSame('foo', (string) $user->getId());
    }
}

我在控制台中收到此错误

PHP Fatal error:  Cannot use User\Contracts\UserId as UserId because the name is already in use in /src/User/User.php on line 5

这是文件/文件夹结构:

src
`-- User
    |-- Contracts
    |    |-- User.php
    |    `-- UserId.php
    |-- User.php
    `-- UserId.php
tests
`-- User
    |-- UserIdTest.php
    `-- UserTest.php

我已经对这个问题进行了很多搜索,但我没有找到任何解决方案。

  • PHP 版本:5.6.13-1+deb.sury.org~trusty+3
  • PHPUnit 版本:5.0.3
  • 操作系统:Ubuntu 14.04.3 LTS

我该如何解决这个问题?

【问题讨论】:

    标签: php phpunit composer-php


    【解决方案1】:

    尝试以下方法:

    use User\Contracts\UserId as UserIdContract;
    

    您可能会遇到命名冲突,因为您正在这样做

    use User\Contracts\UserId;
    

    但您在 User 类的同一命名空间中也有 UserId

    所以...

    namespace User;
    
    use User\Contracts\UserId as UserIdContract;
    use User\Contracts\User as UserContract;
    
    class User implements UserContract
    {
        private $id;
    
        public function __construct(UserIdContract $id)
        {
            $this->id = $id;
        }
    
        public function getId()
        {
            return $this->id;
        }
    }
    

    希望对你有帮助!

    【讨论】:

      【解决方案2】:

      您不能将一个类导入到已在其中声明的具有相同别名的命名空间中。

      您拥有\User\UserId 并希望将\User\Contracts\UserId 导入\User 命名空间。这会使快捷方式 UserId 模棱两可。

      http://php.net/manual/en/language.namespaces.importing.php#117334

      您可以在导入时使用别名,也可以直接使用相对路径:

      namespace User;
      
      class User implements Contracts\User
      {
          private $id;
      
          public function __construct(Contracts\UserId $id) {}
      }
      

      2018-03-20 更新:

      有一个错误报告https://bugs.php.net/bug.php?id=66773 抱怨如果在没有操作码缓存的情况下使用 PHP 会触发此错误,但否则不会。原因是使用 opcache 编译是针对每个文件完成的,并且可以合理地期望只考虑文件的内容。但是,错误似乎是在导入“冲突”类时,来自先前加载的文件的现有类定义会妨碍。

      它以正确的方式在 PHP 7.0.13 中得到了修复:每个文件只说明它自己,如果你想导入一个类并通过它的简写名称使用它,你可以这样做,而不管任何其他类可能存在于命名空间中。您只需放弃对这些类的访问 - 这是无关紧要的,因为您的代码一开始就没有使用它们。如果你想改变它,你必须改变导入。

      由于 opcache 通常在命令行中被禁用,因此您在使用 PHPUnit 时可能会触发此错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-30
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        • 2016-07-08
        • 1970-01-01
        • 1970-01-01
        • 2012-09-07
        相关资源
        最近更新 更多