Laravel5依赖注入模型

时间:2015-11-10 18:21:17

标签: laravel-5 ioc-container

我有一个名为Surface的Eloquent模型,它依赖于ZipCodeRepository对象:

number[n].name = NULL;

和一个包含多个曲面的Address对象。

class Surface extends Model{
    public function __construct(ZipCodeRepositoryInterface $zipCode){...}

我的问题是,当我致电class Address extends Model{ public surfaces() { return $this->hasMany('App/Surface'); } } 时,我收到以下错误:

$address->surfaces

我认为IoC会自动注入。

3 个答案:

答案 0 :(得分:20)

感谢@svmm引用the question mentioned in the comments。我发现你不能在模型上使用依赖注入,因为你必须改变构造函数上的签名,这不能与Eloquent框架一起使用。

在重构代码时,我作为中间步骤所做的是在构造函数中使用App::make来创建对象,例如:

class Surface extends Model{
    public function __construct()
    {
        $this->zipCode = App::make('App\Repositories\ZipCodeRepositoryInterface');
    }

这样IoC仍然可以获取已实现的存储库。我只是这样做,直到我可以将函数拉入存储库以删除依赖项。

答案 1 :(得分:1)

但是,通过构造函数或方法注入将服务注入到您的模型中可能不是一个好习惯,请考虑以不需要这样做的方式设计系统,而是将模型注入到服务中.

让我们看一个例子(只是一个虚拟的例子,以便进入重点!)。

  • 假设我们有篮子和订单模型,我们想将订单添加到篮子
  • 我们有一个折扣服务,可以根据订单计算折扣
  • 每次用户向购物篮添加订单时,我们都需要计算新的折扣并将其设置在购物篮中

一种方法是:

class OrderController
{
    function store(User $user, Order $order)
    {
        $basket = $user->getBasket();
        $basket->addOrder($order);
    }
}

class Basket
{
    private $discountService;

    public function __construct(DiscountService $discountService)
    {
        $this->discountService = $discountService;
    }

    function addOrder(Order $order)
    {
        $this->orders[] = $order;
        $discount = $this->discountService->calculateFor($this->orders);
        $this->discount = $discount;
    }
}

class DiscountService
{
    function calculateFor(array $orders) {
        // code for calculating discount;
        return $discount;
    }
}

在这种方法中,我们将折扣服务注入到篮子模型中

另一种更好的方法是这样的:

class OrderController
{
    private $discountService;

    public function __construct(DiscountService $discountService)
    {
        $this->discountService = $discountService;
    }

    function store(User $user, Order $order)
    {
        $basket = $user->getBasket();
        $basket->addOrder($order);
        $this->discountService->setDiscount($basket);
    }
}

class Basket
{
    function addOrder(Order $order)
    {
        $this->orders[] = $order;
    }

    function getOrders()
    {
        return $this->orders;
    }

    function setDiscount(int $discount)
    {
        $this->discount = $discount;
    }
}

class DiscountService
{
    function setDiscount(Basket $basket) {
        $discount = $this->calculateFor($basket->getOrders());
        $basket->setDiscount($discount);
    }

    private function calculateFor(array $orders)
    {
        // code for calculating discount
        return $discount;
    }
}
  • 在第一种方法中,购物篮是决定是否打折,但这不是购物篮的问题
  • 在第一种方法中,购物篮取决于折扣服务,但在现实世界中,您不需要折扣服务即可拥有购物篮

答案 2 :(得分:0)

在Laravel 5.7中,您可以使用全局resolve(...)方法。我不认为全局App是在最新版本的Laravel中定义的。

$myService = resolve(ServiceName::class);

Resolving in Laravel docs