【问题标题】:Laravel 4 setting up model using the IoC containerLaravel 4 使用 IoC 容器设置模型
【发布时间】:2023-03-17 17:18:01
【问题描述】:

我最近观看了这个视频,想更改我的 Laravel 控制器,以便使用 Laravel 的 IoC 容器管理它们的依赖项。该视频讨论了为模型创建接口,然后为使用的特定数据源实现该接口。

我的问题是:当使用扩展 Eloquent 的类实现接口并将该类绑定到控制器以便可以从 $this->model 访问时,我是否还应该为 Eloquent 模型创建接口和实现,这些模型可能会在何时返回调用方法如$this->model->find($id)? Model 和 ModelRepository 应该有不同的类吗?

换一种说法:当我的模型在$this->model时,我该怎么做new Model

【问题讨论】:

    标签: php laravel laravel-4


    【解决方案1】:

    一般来说,是的,执行该模式(存储库模式)的人有一个接口,其中定义了一些您的应用将使用的方法:

    interface SomethingInterface {
    
        public function find($id);
    
        public function all();
    
        public function paged($offset, $limit);
    
    }
    

    然后你创建一个实现。如果你使用 Eloquent,那么你可以做一个 Eloquent 实现

    use Illuminate\Database\Model;
    
    class EloquentSomething {
    
        protected $something;
    
        public function __construct(Model $something)
        {
            $this->something = $something;
        }
    
        public function find($id)
        {
            return $this->something->find($id);
        }
    
        public function all() { ... }
    
        public function paged($offset, $limit) { ... }
    
    }
    

    然后你创建一个服务提供者把它们放在一起,然后添加到app/config/app.php

    use Something; // Eloquent Model
    use Namespace\Path\To\EloquentSomething;
    use Illuminate\Support\ServiceProvider;
    
    class RepoServiceProvider extends ServiceProvider {
    
        public function register()
        {
            $app = $this->app;
    
            $app->bind('Namespace/Path/To/SomethingInterface', function()
            {
                return new EloquentSomething( new Something );
            });
        }
    
    }
    

    最后,您的控制器可以使用该接口作为类型提示:

    use Namespace/Path/To/SomethingInterface;
    
    class SomethingController extends BaseController {
    
        protected $something;
    
        public function __construct(SomethingInterface $something)
        {
             $this->something = $something;
        }
    
    
        public function home() { return $this->something->paged(0, 10); }
    
    }
    

    应该是这样的。对任何错误表示歉意,这未经测试,但我经常这样做。

    缺点:

    更多代码:D

    优点:

    • 能够切换实现(代替 EloquentSomething,可以使用 ArraySomething、MongoSomething 等),而无需更改控制器代码或任何使用接口实现的代码。
    • 可测试 - 您可以模拟 Eloquent 类并测试存储库,或者模拟您的构造函数依赖项并测试您的控制器
    • 可重复使用 - 您可以 App::make() 在应用中的任何位置获取具体的 EloquentSomething,并在代码中的任何位置重复使用 Something 存储库
    • 存储库是添加额外逻辑的好地方,例如缓存层,甚至是验证规则。库存在您的控制器中乱七八糟。

    最后:,由于我可能已经输入了所有内容,但仍然没有回答您的问题(wtf?!),您可以获取模型的新实例使用$this->model。这是创建新事物的示例:

    // Interface:
    public function create(array $data);
    
    // EloquentSomething:
    public function create(array $data) 
    {
        $something = this->something->newInstance();
        // Continue on with creation logic
    }
    

    关键是这个方法,newInstance()

    【讨论】:

    • 谢谢,这对我也有帮助!我使用 $something = $this->model 从控制器循环中调用 EloquentSomething 的 create(),正如 @user1669496 提到的那样,这导致在第一次迭代中创建 $something,然后在每次后续迭代中更新 $something(当我打算每次迭代都创建一个新的 $something )。按照建议将其修改为 $something = this->something->newInstance() 会导致我的预期行为。
    【解决方案2】:

    我用过$newModel = $this->model,它对我有用。

    【讨论】:

      猜你喜欢
      • 2013-03-11
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 2018-05-24
      • 2018-04-27
      相关资源
      最近更新 更多