【问题标题】:PHP Type Hinting Implementation of Abstract Method - Repository Pattern抽象方法的 PHP 类型提示实现 - 存储库模式
【发布时间】:2016-04-20 11:58:21
【问题描述】:

问题

是否可以使用模型/存储库模式在 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;

一个丑陋的修复

真正获得代码完成的唯一方法似乎是使用新的 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);
    }
}

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

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

【问题讨论】:

  • 在 PHPDoc 中尝试@method 类。
  • @LazyOne - 如果我将 @method User find($id) 添加到 UserRepository 文档块,那确实有效。然而,这仍然意味着我需要为每个存储库和每个返回模型的函数执行此操作。
  • ` ¯\_(ツ)_/¯ ` 1) 至少你不要重新声明它 2) 我不知道其他方法 3) 也许 Laravel 支持插件可以做到这一点(如果你还没有安装)

标签: php laravel phpstorm repository-pattern type-hinting


【解决方案1】:

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


妥协的解决方案

在进一步研究repository和mvc php模式后,我得出的结论是使用更具体和详细的​​repository函数。


错误的方式

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

$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
            }
        );

正确的方式

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

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

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

【讨论】:

    【解决方案2】:

    您可以使用 abstract 关键字来卸载方法的实现。

    abstract class Model {
        abstract public function find($id);
    }
    

    这会强制任何扩展模型的对象实现该功能。

    我希望这是有道理的。

    【讨论】:

      猜你喜欢
      • 2016-01-19
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2017-08-26
      • 1970-01-01
      • 2018-02-17
      相关资源
      最近更新 更多