Laravel ioc automatic resolution - works from controller but not from custom class

半城伤御伤魂 提交于 2019-12-04 08:02:50

The IoC is automatic within controllers, and you don't see the injection because Laravel handles the construction of controllers for you. When creating any other custom class by using the new keyword, you will still need to send in all of the parameters needed to it's constructor:

$myClass = new ClassWithDependency( app()->make('Dependency') );

You can hide this, to a degree, by funneling creation of your custom class through a service provider:

// Your service provider
public function register()
{
    $this->app->bind('ClassWithDependency', function($app) {
        return new ClassWithDependency( $app->make('Dependency') );
    });
}

Then just have the IoC make it whenever you need it:

$myClass = app()->make('ClassWithDepenency');

In your case, you can change your code to look like this:

private function setOffer(Offer $offer = null) {
    $this->processOffer    = $offer ?: 
        new Offer( app()->make('LossControlInterface') );
}

A perhaps cleaner approach could be to create a service provider and an OfferFactory which gets injected into your controller. The controller can then request the factory to create the offer whenever it needs one:

// Controller
public function __construct(OfferFactory $offerFactory)
{
    $this->offerFactory = $offerFactory;
}

public function setOffer(Offer $offer = null)
{
    $this->processOffer = $offer ?: $this->offerFactory->createOffer();
}

// OfferFactory
class OfferFactory
{
    public function createOffer()
    {
        return app()->make('Offer');
    }
}

This has the benefit of completely decoupling your controller from the logic behind the creation of the offer, yet allowing you to have a spot to add any amount of complexity necessary to the process of creating offers.

In Laravel 5.2 the simplest solution for your particular problem would be to replace

new Offer();

with

App::make('Offer');

or even shorter

app('Offer');

which will use Laravel Container to take care of dependencies.

If however you want to pass additional parameters to the Offer constructor it is necessary to bind it in your service provider

App::bind('Offer', function($app, $args) {
    return new Offer($app->make('LossControl'), $args);
});

And voila, now you can write

app('Offer', [123, 456]);

In laravel 5.4 (https://github.com/laravel/framework/pull/18271) you need to use the new makeWith method of the IoC container.

App::makeWith( 'App\MyNameSpace\MyClass', [ $id ] );

if you still use 5.3 or below, the above answers will work.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!