【问题标题】:Laravel 5 IoC type-hinting not workingLaravel 5 IoC 类型提示不起作用
【发布时间】:2015-02-03 23:27:11
【问题描述】:

据我所知,我应该能够在我的类的构造函数中键入提示我的类实例参数,我只能在服务提供者的帮助下实例化。不幸的是,我收到关于缺少参数的错误。

Tracker.php

function __construct($query, Tracker\Shipment $shipment) {
    $this->query    = $query;
    $this->shipment = $shipment;
}

TrackerServiceProvider.php

class TrackerServiceProvider extends \Illuminate\Support\ServiceProvider {
    public function register() {
        $this->app->bind('TrackerAPI',  function($app, $shipment_number) {
            return new Tracker\API($shipment_number); // omitting Shipment argument should resolve on its own?
        });
    }
}

类 API 正在扩展 Tracker,因此使用了它的构造函数。为什么没有隐含的类类型提示就无法解决?

【问题讨论】:

    标签: php laravel inversion-of-control laravel-5


    【解决方案1】:

    不。 Laravel 无法解决这样的部分问题。你必须明确:

    use Tracker\API;
    use Tracker\Shipment;
    use Illuminate\Support\ServiceProvider;
    
    class TrackerServiceProvider extends ServiceProvider {
    
        public function register()
        {
            $this->app->bind('TrackerAPI',  function($app, $shipment_number)
            {
                return new API($shipment_number, $app[Shipment::class]);
            });
        }
    }
    

    【讨论】:

    • 感谢您的回答。但是为什么我误解了类型提示和自动解析的概念呢?还是只适用于接口而不适用于类?
    • 查询参数没有类型提示。 Laravel 不知道在构造上传递什么。服务提供者明确说明了每次实例化对象时应该传递的内容。
    【解决方案2】:

    您将 PHP new 功能与 Laravel 通过类型提示功能进行的依赖注入混淆了。

    在您的TrackerAPI 绑定中,当您指定return new Tracker\API($shipment_number); 时,PHP 没有内置任何东西来尝试充实任何缺失的参数。为此,您需要return $app->make('Tracker\API', [$shipment_number]);

    当你使用App::make() 方法时,Laravel 会施展魔法来创建一个新对象。它首先检查显式定义的绑定。如果它没有找到显式绑定,它将退回到仅使用提供的参数和类型提示的组合来为任何缺少的参数创建对象。

    采取以下语句:App::make('Tracker\API', [$shipment_number])。假设Tracker\API 没有明确定义的绑定。 Tracker\API 构造函数需要两个参数。 $shipment_number是在参数数组中传入的,所以会作为第一个参数。由于只提供了一个参数,Laravel 将使用类型提示 App::make() 其余参数。

    但是,当您使用 new 关键字自己专门实例化对象时,这一切都不会发生。它是一个普通的 PHP 对象实例化。

    【讨论】:

    • 那么你的意思是如果我放弃我的绑定(服务提供者)并立即在我的控制器中使用App::make(Tracker\API),它会像我最初想象的那样工作吗?
    • @silkfire 可以,只要你传入无法通过类型提示构建的参数(比如你的$shipment_number)。如果你试图做一些 Laravel 自己无法解决的事情,你只需要定义你的绑定。例如,如果你要注入一个接口,你需要创建一个绑定来告诉 Laravel 为那个接口构建什么实例。或者,如果您不想注入 new 实例,而是要注入现有实例(例如,如果您要注入 Sentry 服务)。
    • 非常感谢!我只是使用了 make 方法,在数组中提供了发货编号,它会自动神奇地自行解析。那时我实际上不需要服务提供商!一方面是好的,但现在我对何时需要它们感到更加困惑。我从来不必确保使用同一个类的实例,然后我只需在我的代码中重用已经创建的变量...
    猜你喜欢
    • 2013-07-21
    • 2018-03-31
    • 1970-01-01
    • 2018-03-07
    • 2016-01-30
    • 2017-08-14
    • 1970-01-01
    • 2016-04-22
    • 2020-02-17
    相关资源
    最近更新 更多