为简洁起见省略了命名空间...
我已经编写了以下服务提供者并在 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/