4
votes

I am currently refactoring my Laravel 5 project in order to make use of the Repository Design Pattern.

I have a created repository interface and a repository class:

interface UserRepositoryInterface {
    [...]
}

class UserRepository implements UserRepositoryInterface
{
   [...]
}

then added the necessary binding in the service provider class:

App::bind('App\Repositories\UserRepositoryInterface','App\Repositories\UserRepository');

and the injected the interface into the controller constructor:

class UserController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(UserRepositoryInterface $userRepository)
    {
        $this->userRepository = $userRepository;
    }
}

This part works fine. The problem is that I need to use some of the repository methods in the app\Console\Kernel.php class, where I implemented some scheduled tasks. I tried injecting the Kernel constructor in a similar fashion:

/**
 * Create a new console kernel instance.
 */
public function __construct(Application $app, Dispatcher $events, UserRepositoryInterface $userRepository)
{
    parent::__construct($app, $events);

    $this->userRepository = $userRepository;
}

However, this approach does not work (e.g. running 'php artisan tinker' in the Terminal fails). I get the following error:

PHP Fatal error: Uncaught Illuminate\Contracts\Container\BindingResolutionException: Target [App\Repositories\UserRepositoryInterface] is not instantiable while building [App\Console\Kernel]. in D:\xampp\htdocs\budget-and-expe nse-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:752 Stack trace:

0 D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php(633):

Illuminate\Container\Container->build('App\Repositorie...', Array)

1 D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(697):

Illuminate\Container\Container->make('App\Repositorie...', Array)

2 D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php(853):

Illuminate\Foundation\Application->make('App\Repositorie...')

3 D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php(808):

Illuminate\C in D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illum inate\Container\Container.php on line 752

Fatal error: Uncaught Illuminate\Contracts\Container\BindingResolutionException: Target [App\Repositories\UserRepositoryInterface] is not instantiable while building [App\Console\Kernel]. in D:\xampp\htdocs\budget-and-expense-m anagement\local\vendor\laravel\framework\src\Illuminate\Container\Container.php on line 752

Illuminate\Contracts\Container\BindingResolutionException: Target [App\Repositories\UserRepositoryInterface] is not instantiable while building [App\Console\Kernel]. in D:\xampp\htdocs\budget-and-expense-management\local\vendor \laravel\framework\src\Illuminate\Container\Container.php on line 752

Call Stack: 0.0006 345568 1. {main}() D:\xampp\htdocs\budget-and-expense-management\local\artisan:0 0.0365 1417504 2. Illuminate\Foundation\Application->make() D:\xampp\htdocs\budget-and-expense-management\local\artisan:31 0.0365 1417552 3. Illuminate\Container\Container->make() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:697 0.0367 1417552 4. Illuminate\Container\Container->build() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:633 0.0367 1417552 5. Illuminate\Container\Container->Illuminate\Container{closure}() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:735 0.0367 1417576 6. Illuminate\Foundation\Application->make() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:230 0.0367 1417576 7. Illuminate\Container\Container->make() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:697 0.0368 1417576 8. Illuminate\Container\Container->build() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:633 0.0388 1453584 9. Illuminate\Container\Container->getDependencies() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:777 0.0397 1456432 10. Illuminate\Container\Container->resolveClass() D:\xampp\htdocs\budget-and-expense-management\local\vendor\laravel\framework\src\Illuminate\Container\Container.php:808

I would like to know if it is at all possible to inject a repository interface into the Kernel, and, if yes, what am I doing wrong?

1
I don't know if it is possible, but $userRepository = \App::make('App\Repositories\UserRepositoryInterface') should work fine and basically has the same result (though DI is probably cleaner and easier to test, but who tests the Kernel anyway?)Pevara

1 Answers

7
votes

You are doing it wrong. I suppose you wrote your scheduled tasks directly in the Kernel in closures. Instead, wrap your commands logic in Console commands

<?php

namespace App\Console\Commands;

use App\Repositories\UserRepository;
use Illuminate\Console\Command;

class MyCoolCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'mycool:command';

    protected $repository = null;

    public function __construct(UserRepository $repository)
    {
        parent::__construct();

        $this->repository = $repository;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // your logic here
    }

}

and then call them in the kernel like this:

$schedule->command('mycool:command')->daily();

You can then define each command dependencies separately in the command constructor, clean up your kernel and write some testable and pretty code :)