为什么在 Laravel 构造函数中访问 Facade 会失败?

Why does accessing a Facade in a Laravel constructor fail?

我目前正在尝试在 Laravel 中实现存储库模式。

我有一个接口声明了成为有效存储库所需的最少方法。

<?php

namespace App\Repositories;

interface RepositoryInterface
{
    public function all();

    public function create($entity);

    public function update($entity);

    public function find($id);

    public function delete($entity);
}

我有一个抽象 class 表示我存储库中的接口方法,如下所示:

namespace App\Repositories;

use DB;

abstract class DbRepository
{
    public function all()
    {
        return DB::table($this->tableName)->get();
    }

    public function create($user)
    {
        return $user->save();
    }

    public function update($user)
    {
        return $user->update();
    }

    public function find($id)
    {
        return DB::table($this->tableName)->where('id', $id)->first();
    }

    public function delete($user)
    {
        return $user->delete();
    }
}

还有一个 UserRepository 实现接口并从抽象 class 继承,如下所示:

namespace App\Repositories;

use App\Models\User;

class UserRepository extends DbRepository implements RepositoryInterface
{

    public $tableName;

    public function __construct($tableName = 'users')
    {
        $this->tableName = $tableName;
    }

    /**
     * Override the parent find method, as we want to return an instance of App\Models\User instead of stdClass
     * @param $id
     * @return mixed
     */
    public function find($id)
    {
        return User::where('id', $id)->first();
    }
}

以上一切正常,我的单元测试通过了。但是,我决定将当前数据库 table 作为存储库抽象实现的 属性 保存会很好,因此我将 class 重构为如下所示:

abstract class DbRepository implements RepositoryInterface
{
    private $table;

    public function __construct()
    {
        $this->table = DB::table($this->tableName);
    }

    public function all()
    {
        return $this->table->get();
    }
    # etc, etc...

然后确保从存储库的构造函数调用了抽象 class' 构造函数:

public function __construct($tableName = 'users')
{
    $this->tableName = $tableName;
    parent::__construct();
}

执行此操作后,我收到以下错误,我无法修复 Error: Class 'DB' not found 当 运行 PhpUnit.

我知道这个错误与我尝试重构事物的方式有关。我认为这与尝试在抽象 class 的构造函数中访问 DB Facade 有关(因为在同一 class 中的其他方法中访问 DB 很好)。任何解释将不胜感激 - 我很好奇为什么它不起作用。

我已经将它还原为原始代码(这很好,真的)并且测试再次通过!

哦,如果你想查看我的测试,它们是:

namespace Tests\Repositories;

use TestCase;
use App\Repositories\UserRepository;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class UserRepositoryTest extends TestCase
{
    use DatabaseMigrations;

    private $repository;

    public function __construct()
    {
        $this->repository = new UserRepository();
    }

    public function newUser()
    {
        return new User([
            'name' => 'Joe',
            'username' => 'joe',
            'password' => bcrypt('password'),
            'email' => 'joe@apple.com'
        ]);
    }

    public function test_all_method_returns_all_users()
    {
        $this->assertNotNull($this->repository->all());
    }

    public function test_create_user()
    {
        $this->assertTrue($this->repository->create($this->newUser()));
    }

    public function test_update_user()
    {
        // Arrange
        $user = $this->newUser();

        // Act
        $this->repository->create($user);
        $user->name = 'Jack';

        // Assert
        $this->assertTrue((integer)$this->repository->update($user) === 1);
    }

    public function test_delete_user()
    {
        // Arrange
        $user = $this->newUser();

        // Act
        $this->repository->create($user);

        // Assert
        $this->assertTrue((integer)$this->repository->delete($user) === 1);
    }

    public function test_find_user()
    {
        // Arrange
        $user = $this->newUser();

        // Act
        $this->repository->create($user);

        // Assert
        $this->assertInstanceOf(User::class, $this->repository->find($user->id));
    }
}

不要在测试用例中覆盖 __construct()

测试用例是在早期实例化的,并且还依赖于您不调用的PHPUnit_Framework_TestCase constructorDB 的自动加载器此时可能尚未初始化。

改用 setUp(),它在每次测试之前都会被调用,并且是为这种初始化而设计的:

protected function setUp()
{
    $this->repository = new UserRepository();
}