在PHPUnit中使用composer的自动加载已经使用名称致命错误

Fed*_*ddu 2 php phpunit composer-php

当我尝试测试这个类时,使用PSR-4自动加载Composer:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用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());
    }
}
Run Code Online (Sandbox Code Playgroud)

我在控制台中收到此错误

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
Run Code Online (Sandbox Code Playgroud)

这是文件/文件夹结构:

src
`-- User
    |-- Contracts
    |    |-- User.php
    |    `-- UserId.php
    |-- User.php
    `-- UserId.php
tests
`-- User
    |-- UserIdTest.php
    `-- UserTest.php
Run Code Online (Sandbox Code Playgroud)

我已经对这些问题进行了大量搜索,但我没有找到任何解决方案.

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

我怎么解决这个问题?

Sve*_*ven 5

您不能将类导入已使用相同别名在其中声明的命名空间.

你必须\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) {}
}
Run Code Online (Sandbox Code Playgroud)

更新2018-03-20:

有一个错误报告https://bugs.php.net/bug.php?id=66773,如果在没有操作码缓存的情况下使用,则会抱怨PHP触发此错误,但不是.原因是使用opcache编译是按文件完成的,并且合理的期望是仅考虑文件的内容.但是,似乎错误是以前加载的文件中的现有类定义在导入"冲突"类时会受到影响.

它以正确的方式修复了PHP 7.0.13:每个文件只能自己编写,如果你想导入一个类并按照它的简写名称使用它,你可以这样做而不管其中可能存在的任何其他类.命名空间.您只是松开了对这些类的访问 - 这是无关紧要的,因为您的代码首先不使用它们.如果您想要更改,则必须更改导入.

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