具有单例的ServiceProvider在控制器方法DI中询问原始类型

时间:2019-02-18 18:15:24

标签: php laravel laravel-5 autowired service-provider

我正在尝试为Laravel应用程序中的重复代码创建ServiceProvider。我的解决方案引发异常:

Illuminate \ Contracts \ Container \ BindingResolutionException:

Unresolvable dependency resolving [Parameter #0 [ <required> string $shortName ]] in class App\Domain\Translation\GetTranslation

我有一个自定义的抽象控制器,其中有一个简单的单例函数:

namespace App\Http\Controllers\WWW;

class CustomController {
(...)
        app()->singleton(
            GetTranslation::class, function() {
            return new GetTranslation(
                TrimSuffixFromUrl::getShortName(),
                LanguageMap::getLanguageIdByCode(\LaravelLocalization::getCurrentLocale()),
                app()->make(CurrentLanguage::class)
            );
        });
(...)
}

此单例在名为CreateAccount的具体控制器中使用:

class CreateAccount extends ControllerWWW
{
    public function index(Request $request, DbInstanceFactory $dbInstance, GetTranslation $translation)
    {
        $getTranslation = $translation; // For simplify this example I remove logic
        // (...)
    }

我要创建ServiceProvider

<?php 
declare(strict_types=1);

namespace App\Providers;

use App\Domain\Domains\Prefix\TrimSuffixFromUrl;
use App\Domain\Language\CurrentLanguage;
use App\Domain\Translation\GetTranslation;
use App\Repository\LanguageMap;
use Illuminate\Support\ServiceProvider;

/**
 * Class TranslatioServiceProvider
 * @package App\Providers
 */
class TranslationServiceProvider extends ServiceProvider
{
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register(): void
    {
        app()->singleton(
            GetTranslation::class, function() {
                return new GetTranslation(
                    TrimSuffixFromUrl::getShortName(),
                    LanguageMap::getLanguageIdByCode(\LaravelLocalization::getCurrentLocale()),
                    app()->make(CurrentLanguage::class)
                );
            }
        );
    }

    /**
     * @return array
     */
    public function provides(): array
    {
        parent::provides();

        return [GetTranslation::class];
    }
}

然后将此服务添加到app.php

'providers' => [
    App\Providers\TranslationServiceProvider::class,
]

我知道Laravel会尝试解决此服务的依赖关系,但我不知道如何编写此代码来解析控制器中的原语。

另一方面,此类-GetTranslation-与我的视图有关,例如:

<?php
// resources/lang/br/validation.php
declare(strict_types=1);

$translation = app()->make(\App\Domain\Translation\GetTranslation::class);

return [
    'required' => $translation->getTranslationsByKey('tranlation_my_key')
];

如何在控制器和视图中运行此服务提供者-但是我不需要在抽象控制器中运行->singleton()方法。我认为此方法的位置在Provider文件夹中,而不在控制器中。

1 个答案:

答案 0 :(得分:0)

我以这种方式解决了这个问题:

  1. 创建TranslationInterface-甚至是空的。
  2. GetTranslation::class中实现此界面,例如:
class GetTranslation implements TranslationInterface {}
  1. 我找到了app()->make(GetTranslation::class);的所有用法并将其替换为app()->make(TranslationInterface::class);