PHP类型提示抽象方法的实现 - 存储库模式

mag*_*ito 5 php type-hinting repository-pattern phpstorm laravel

是否可以使用模型/存储库模式在PhpStorm中获得行代码完成?

我的设置

我正在使用Laravel并实现Laracasts视频中描述的存储库模式.

代码

下面是模型在Laravel中如何工作的基本示例,以及如何无法获得模型属性的代码完成.

这段代码可以正常工作并打印出'billy',但属性$ name不是类型提示,也不会在PhpStorm中完成代码.类型提示是优先考虑父属性定义类型而不是子元素,这对我来说似乎很奇怪.

<?php

// Models
abstract class Model {
    public $sqlTableName;

    public function findFromDatabase($id)
    {
        $model = new $this;

        // This would be grabbed using table name and $id
        $fakeDatabaseRow = ['name' => 'billy', 'job' => 'engineer'];

        foreach ($fakeDatabaseRow as $column => $value) {
            $model->$column = $value;
        }

        return $model;
    }
}

class User extends Model {
    public $name;
    public $job;

    public $sqlTableName = 'users';
}

// Repositories
abstract class RepositoryBase {
    /**
     * @var Model
     */
    public $model;

    public function find($id)
    {
        $this->model = $this->model->findFromDatabase(1);

        return $this->model;
    }
}

class UserRepository extends RepositoryBase {
    /**
     * @var User
     */
    public $model;

    public function __construct(User $model)
    {
        $this->model = $model;
    }
}

// Run
$model = new User();

$userRepository = new UserRepository($model);

echo $userRepository->find(1)->name;
Run Code Online (Sandbox Code Playgroud)

丑陋的修复

实际获得代码完成的唯一似乎是使用新的php doc块重新定义子函数:

class UserRepository extends RepositoryBase {
    /**
     * @var User
     */
    public $model;

    public function __construct(User $model)
    {
        $this->model = $model;
    }

    // I need to replace this function for every different repository
    // even though they are all the same
    /**
     * @param $id
     * @return User
     */
    public function find($id)
    {
        return parent::find($id);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我有数百个模型,存储库和存储库功能.重写每个实现中的所有函数将是一项巨大的工作.

有没有办法让PhpStorm使用孩子的类型提示声明而不是父母而不必重新声明方法?

mag*_*ito 2

我无法找到解决方案来在我最初发布此问题的上下文中获得模型和存储库的正确类型提示。


妥协的解决方案

在进一步研究存储库和 mvc php 模式之后,我得出的结论是使用更具体和详细的​​存储库功能。


错误的方法

例如,我在控制器/逻辑类中使用存储库基本函数,如下所示:

$users =
    $userRepository->where('created_at', '<', '2016-01-18 19:21:20')->where(
            'permission_level',
            'admin'
        )->orderBy('created_at')->get('id');

$posts =
    $postRepository->where('posted_on', '<', '2016-01-18 19:21:20')
        ->where('content', '!=', 'null')
        ->chunk(
            function ($posts) {
                // do things
            }
        );
Run Code Online (Sandbox Code Playgroud)

正确的方式

现在,我在特定存储库中为我的所有需求编写了单独的数据库逻辑函数,因此我的核心类/控制器最终看起来像这样:

$users = $userRepository->getAdminIdsCreatedBeforeDate('2016-01-18 19:21:20');
$posts = $postRepository->chunkFilledPostsBeforeDate('2016-01-18 19:21:20', function() {});
Run Code Online (Sandbox Code Playgroud)

这样,所有数据库逻辑都会移动到特定存储库,我可以输入提示它返回的模型。这种方法还可以使代码更清晰、更易于阅读,并进一步将核心逻辑与 Eloquent 分开。