Laravel:命令中的依赖注入

Posted

技术标签:

【中文标题】Laravel:命令中的依赖注入【英文标题】:Laravel: dependency injection in commands 【发布时间】:2016-10-05 11:33:59 【问题描述】:

command 中的 自定义类 的依赖注入是否可能?

我正在尝试这个:

<?php

namespace vendor\package\Commands;

use Illuminate\Console\Command;
use vendor\package\Models\Log;
use vendor\package\Updates\UpdateStatistics;

class UpdatePublishmentStats extends Command

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'vendorname:updatePublishmentStats';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Updates Twitter followers & Facebook page likes';

    /**
     * Contact implementation
     * @var vendor\package\Update\UpdateStatistics
     */
    protected $stats;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct(
        Log $log,
        UpdateStatistics $stats
    ) 
        parent::__construct();
        $this->log = $log;
        $this->stats = $stats;
    

但是当我尝试这样做时:

public function handle()

    $this->stats->updateFbStats();


突然收到Segmentation fault: 11

当我删除 use vendor\package\Updates\UpdateStatistics; 部分时,我没有收到该错误。

那么我在这里做错了什么?不能在命令中使用依赖注入吗?

【问题讨论】:

【参考方案1】:

您可以在handle 方法中注入任何服务:

请注意,我们可以将所需的任何依赖项注入到命令的 handle 方法中。

来源:https://laravel.com/docs/5.8/artisan#command-structure

【讨论】:

【参考方案2】:

根据 5.2 文档 (https://laravel.com/docs/5.2/artisan#writing-commands) 的命令结构部分:

“请注意,我们可以将所需的任何依赖项注入命令的构造函数。Laravel 服务容器将自动注入构造函数中类型提示的所有依赖项。”

所以我认为你在这方面做得很好,就目前和可用的能力而言。

至于让它工作,对我来说,段错误指出了 UpdateStats 类的问题,它是如何在服务容器中引用的,或者它是如何从服务容器中解析出来的。

我没有明确的答案,但我会尝试另一个类,看看我是否可以将问题本地化到这个特定的类,或者问题是否发生在其他类中,然后尝试从那里进行调试。

另外,如果你不能让它工作,app() 函数会在你需要的时候解析服务容器中的项目(虽然通过 5.2 文档我看不到它了,所以它可能是已弃用 - 我确实看到了 $this-&gt;app-&gt;make())。

如果没有其他方法,这可能对您有用:

public function __construct(
    Log $log,
) 
    parent::__construct();
    $this->log = $log;
    $this->stats = app(UpdateStatistics::class);

但是,我的猜测是,您也会因此遇到段错误,因为它应该尝试以相同的方式解决同一个类。如果你这样做了,那么至少错误会更清楚一点,并且与自动注入功能无关。

希望至少能有所帮助。


app() 函数更新

所以app() 函数似乎没有记录在案,但我现在安装了 5.2 并且 Illuminate/Foundation 中的 helpers.php 文件肯定具有该函数:

if (! function_exists('app')) 
    /**
     * Get the available container instance.
     *
     * @param  string  $make
     * @param  array   $parameters
     * @return mixed|\Illuminate\Foundation\Application
     */
    function app($make = null, $parameters = [])
    
        if (is_null($make)) 
            return Container::getInstance();
        

        return Container::getInstance()->make($make, $parameters);
    

很遗憾,API 文档不包含任何辅助函数,但 Github 上文件的当前 master、5.2 和 5.3 版本都有该函数:

https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/helpers.php#L91 https://github.com/laravel/framework/blob/5.3/src/Illuminate/Foundation/helpers.php#L91 https://github.com/laravel/framework/blob/5.2/src/Illuminate/Foundation/helpers.php#L91

【讨论】:

将依赖项注入构造函数时要小心,因为如果您注入的任何类查询数据库,您的测试可能会由于 Laravel 在运行迁移之前解析注入的依赖项而中断 - 当创建应用程序,即

以上是关于Laravel:命令中的依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

无法在Laravel 5.2中的中间件中注入依赖项

laravel中的构造函数依赖注入理解

看laravel源码学习依赖注入

Laravel:依赖注入身份验证

译深入研究 Laravel 的依赖注入容器

Laravel:如何模拟依赖注入类方法