php - Laravel ioc 自动解析 - 从 Controller 工作但不是从自定义类工作

标签 php laravel repository-pattern ioc-container

为简洁起见省略了命名空间...

我已经编写了以下服务提供者并在 config/app.php 中注册:

class OfferServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->registerLossControlManager();
    }

    protected function registerLossControlManager()
    {
        $this->app->bind('LossControlInterface', 'LossControl');
    }
}

这是我的 LossControlInterface

interface LossControlInterface
{
    /**
     * @param int $demandId
     * @param float $offerTotal
     * @param float $productTotal
     * @param null|int $partnerId
     * @return mixed
     */
    public function make($demandId, $offerTotal, $productTotal, $partnerId = null);

    /**
     * @return float
     */
    public function getAcceptableLoss();

    /**
     * @return bool
     */
    public function isAcceptable();

    /**
     * @return bool
     */
    public function isUnacceptable();

    /**
     * @return null
     */
    public function reject();
}

现在在 Controller 中,我可以按如下方式注入(inject) LossController:

use LossControlInterface as LossControl;

class HomeController extends BaseController {
   public function __construct(LossControl $lossControl)
    {
        $this->lossControl = $lossControl;
    }

    public function getLossThresholds()
    {
        $lossControl = $this->lossControl->make(985, 1000, null);

        var_dump('Acceptable Loss: ' . $lossControl->getAcceptableLoss());
        var_dump('Actual Loss: ' . $lossControl->calculateLoss());
        var_dump('Acceptable? ' . $lossControl->isAcceptable());

    }
}

但是,如果我尝试从命令调用的自定义类中依赖注入(inject) LossControlInterface:

[2014-09-02 13:09:52] development.ERROR: exception 'ErrorException' with message 'Argument 11 passed to Offer::__construct() must be an instance of LossControlInterface, none given, called in /home/vagrant/Code/.../ProcessOffer.php on line 44 and defined' in /home/vagrant/Code/.../Offer.php:79

看起来好像我无法将接口(interface)依赖注入(inject)到自定义类中,但是当依赖注入(inject)到 Controller 中时我可以。

关于我做错了什么或遗漏了自动解决方案的任何想法?

最佳答案

IoC 在 Controller 中是自动的,您看不到注入(inject),因为 Laravel 会为您处理 Controller 的构造。使用 new 关键字创建任何其他自定义类时,您仍然需要将所有需要的参数发送到它的构造函数:

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

您可以在一定程度上隐藏这一点,方法是通过服务提供商汇集您自定义类的创建:

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

然后让 IoC 在您需要时创建它:

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

在您的情况下,您可以将代码更改为如下所示:

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

也许更简洁的方法是创建一个服务提供者和一个注入(inject)到您的 Controller 中的 OfferFactory。然后 Controller 可以请求工厂在需要时创建报价:

// 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');
    }
}

这样做的好处是可以将您的 Controller 与优惠创建背后的逻辑完全分离,同时让您有机会为创建优惠的过程添加任何必要的复杂性。

关于php - Laravel ioc 自动解析 - 从 Controller 工作但不是从自定义类工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25623638/

相关文章:

c# - 将服务注入(inject)另一个服务是不好的做法吗?

php - 将旧的 php url 重定向到新的 Flask url

php - 如何在php中恢复备份的mysql文件

c# - 我应该如何在事务中包装我的选择语句?

asp.net-mvc-3 - 将经过身份验证的用户依赖注入(inject)我的存储库类的正确方法

php - 如何联合/合并具有精确架构但不同数据的三个数据库表,同时处理 Eloquent 关系?

php - 从 php 插入时如何向记录添加文本?

java - 使用Java从网站读取php文件?

php - 导致 sum() 到多个结果的分组表

php - 同一队列中多台机器上的 Laravel 队列监听器