phplaraveldependency-injectionlaravel-8

Laravel Service Provider is not injecting values into Service class


I have a service provider called "MyServiceProvider.php":

<?php

namespace App\Providers;

use App\Services\MyService;
use Illuminate\Support\ServiceProvider;

class MyServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('my_service', function ($app) {
            return new MyService(
                config('services.my_service.url'),
                config('services.my_service.secret')
            );
        });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

I have registered it inside app.php file inside providers array. I checked inside app() config, so there is the provider with the resolved env values, look everything good.

Then I have my Service class:

<?php

namespace App\Services;

class MyService
{
    protected string $url;
    protected ?string $secret;

    public function __construct(string $url = '', ?string $secret = '')
    {
        $this->url = $url;
        $this->secret = $secret;
    }

    public function test()
    {
        return $this->url;
    }
}

Then I want to inject this class into my controller and call test() method to check if the url is resolved. I'm doing like this:

class TestingController extends Controller
{
    protected MyService $myService;

    public function __construct(MyService $myService)
    {
        $this->myService = $myService;
    }

I'm injecting as depedency it. Now I'm calling it inside a route:

    public function testingRoute()
    {
        try {
                $testResult = $this->myService->test();
                dd($testResult);

And I'm every time just getting the empty string (initial value). If I don't set the initial value then I've got an error which tells:

Illuminate\Contracts\Container\BindingResolutionException
Unresolvable dependency resolving [Parameter #0 [ <required> string $url ]] in class App\Services\MyService

I have tried to directly inject into the parameter of testingRoute controller method wihout the initiating constructor but still I've get always the same - Class get's initiated without the provided values whichs my service provider should feed it.

What is happening? I think service provider must create an instance with my configuration before I inject the class by myself? Why I can't get it to work?

Also want to mention that when I call like this:

$myService = app('my_service');

Then it gets initiated with no problem. I'm going out of my mind, need help masters :)


Solution

  • Instead of using 'my_service', use the fully qualified class name.

    $this->app->bind(MyService::class, function ($app) {
                return new MyService(
                    config('services.my_service.url'),
                    config('services.my_service.secret')
                );
            });
    

    Thats because when youre in the __construct method, it will try to find by the class name and not by 'my_service' that you registered in the Service Provider.