【问题标题】:Injecting Artisan into Service class将 Artisan 注入服务类
【发布时间】:2016-02-25 19:15:54
【问题描述】:

我正在尝试将 Artisan 注入到服务中,这样我就可以避免使用外观。 查看外观类引用,我可以看到我应该注入的类是:

Illuminate\Console\Application

所以我会假设这样做:

<?php

namespace App\Service;

use Illuminate\Console\Application;

class DummyDataService
{
    /**
     * @var Application
     */
    private $application;

    public function __construct(
        Application $application
    ) {
        $this->application = $application;
    }

    public function insertDummyData()
    {
        $this->application->call('db:seed', [
            '--class' => 'DummyDataSeeder'
        ]);
    }
}

...会起作用的。但是,我收到以下错误:

BindingResolutionException in Container.php line 824:
Unresolvable dependency resolving [Parameter #2 [ <required> $version ]] in class Illuminate\Console\Application

如果我像这样调用外观上的方法,它就可以工作:

Artisan::call('db:seed', [
    '--class' => 'DummyDataSeeder'
]);

到目前为止,我无法弄清楚问题所在。有没有人遇到过类似的问题?我尽量避免使用外墙。

提前致谢。

【问题讨论】:

    标签: php laravel laravel-5 laravel-artisan laravel-facade


    【解决方案1】:

    你应该注入 Illuminate\Contracts\Console\Kernel 而不是 Illuminate\Console\Application 来实现你想要的,所以你的类应该是这样的:

    <?php
    
    namespace App\Service;
    
    use Illuminate\Contracts\Console\Kernel;
    
    class DummyDataService
    {
        private $kernel;
    
        public function __construct(Kernel $kernel) 
        {
            $this->kernel = $kernel;
        }
    
        public function insertDummyData()
        {
            $this->kernel->call('db:seed', [
                '--class' => 'DummyDataSeeder'
            ]);
        }
    }
    

    【讨论】:

    • 太棒了,这很有效,所以我标记为正确答案。感谢您的帮助。
    • 只是想跟进并说这个解决方案不仅有效,而且完全是正确的参考。文档实际上是错误的。我在一个已经合并的 PR 中更正了它们,所以现在一切都应该适合未来检查的人。
    【解决方案2】:

    如果您查看Illuminate\Console\Application 的构造函数,您会发现它需要$version 参数并且不提供任何类型的默认值。因此,如果没有显式提供它,它将因为这种依赖关系而失败。老实说,这对我来说似乎是一个错误。如果您查看它的 Symphony 父类,您会看到它在其构造函数中提供了一个默认字符串 'UNKNOWN'。如果您修改 Illuminate\Console\Application 以具有相同的默认值,那么您在代码中的命令现在应该可以工作了。

    这让您有两个选择。

    1. 在这个实例中只使用 Artisan 外观。对其余的门面使用构造函数注入应该没问题,因为这会特别影响 Artisan 门面。
    2. 将源代码中的构造函数更改为默认值。不理想,因为每次更新 Laravel 时所有更改都会丢失,但这是一种选择。您也许可以创建某种服务提供程序,将一个版本也注入到所有 Illuminate\Console\Application 实例中,但我不确定。

    老实说,我不确定将默认值添加到构造函数中是否会产生不可预见的后果,尽管我想它们会是最小的,因为它必须在任何地方显式定义它被调用。我什至可以把它做成一个 PR,看看 Taylor 是在上面还是合并它。

    【讨论】:

    • 是的,这对我来说似乎也是一个错误。感谢您的建议。我现在已经恢复使用外观,但会继续挖掘。
    猜你喜欢
    • 1970-01-01
    • 2020-09-09
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    相关资源
    最近更新 更多