php - Why my interface is not instantiable when handle a command?

Laravel CQRS

I am applying CQRS in Laravel just to learn how to use it.

I created a simple user registration and a controller that creates a command to dispatch the handle and use the right use case.

When Trying to use the interface in the controller, it looks like that I need to bind the interface and the implementation because it doesn't know which one to use but in this case I don't really understand how to bind the interface.

CreateUserController.php

<?php
    
    declare(strict_types=1);
    
    namespace App\Http\Controllers\User;
    use App\Http\Controllers\Controller;
    use App\Http\Requests\Users\CreateUserRequest;
    use Illuminate\Http\RedirectResponse;
    
    class CreateUserController extends Controller
    {
        public function __construct(private \Src\User\Infrastructure\CreateUserController $userController)
        {
        }
    
        public function __invoke(CreateUserRequest $request): RedirectResponse
        {
            $this->userController->__invoke($request);
    
            return redirect()->route('verify');
        }
    }

Src\User\Infrastructure\CreateUserController

<?php

declare(strict_types=1);

namespace Src\User\Infrastructure;

use App\Http\Requests\Users\CreateUserRequest;
use Src\Shared\Domain\Bus\Command\CommandBus;
use Src\User\Application\Create\CreateUserCommand;    

final class CreateUserController
{    
    public function __construct(private CommandBus $commandBus)
    {
    }

    public function __invoke(CreateUserRequest $request)
    {
        $name = $request->name;
        $email = $request->email;
        $password = $request->password;

        $command = new CreateUserCommand($name, $email, $password);
        $this->commandBus->dispatch($command);
    }
}

CommandBus

<?php

declare(strict_types=1);

namespace Src\Shared\Domain\Bus\Command;

interface CommandBus
{
    public function dispatch(Command $command): void;
}

Command

<?php

declare(strict_types=1);

namespace Src\Shared\Domain\Bus\Command;

interface Command
{
}

CreateUserCommandHandler

<?php

declare(strict_types=1);

namespace Src\User\Application\Create;

use Src\User\Domain\ValueObjects\UserEmail;
use Src\User\Domain\ValueObjects\UserName;
use Src\User\Domain\ValueObjects\UserPassword;

final class CreateUserCommandHandler
{
    public function __construct(
        private UserCreator $creator
    )
    {
    }

    public function __invoke(CreateUserCommand $command)
    {
        $name = new UserName($command->name());
        $email = new UserEmail($command->email());
        $password = new UserPassword($command->password());

        $this->creator->__invoke($name, $email, $password);
    }
}

The Error

enter image description here

I tried this:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Src\Shared\Domain\Bus\Command\Command;
use Src\User\Application\Create\CreateUserCommand;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(
            Command::class,
            CreateUserCommand::class
        );
    }

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

Answer

Solution:

Here is how you can bind with the interface.

Create a class in app/Providers folder. You can give any name to this class. Eg. InterfaceServiceProvider. extends it with Illuminate\Support\ServiceProvider

namespace App\Providers;
use Illuminate\Support\ServiceProvider;

class InterfaceServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(YourInterFace::class, YourController::class);
    }

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

Add this InterfaceServiceProvider in config/app.php in providers array Eg.

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

Source