Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 - Interface is not instantiable

I know that this question was asked so many times, but none of answers helped me.

I'm getting exception in Laravel 5

BindingResolutionException in Container.php line 785:
Target [App\Contracts\CustomModelInterface] is not instantiable.

What I've done without success:

  • Register App\Providers\AppRepositoryProvider in app.php providers
  • php artisan clear-compiled
  • Everything works if I replace interfaces on repositories in MyService, but I feel that it's wrong (should it be handled by IoC container?).

Structure:

app
  - Contracts
    - CustomModelInterface.php
  - Models
    - CustomModel.php
  - Repositories
    - CustomModelRepository.php
  - Providers
    - AppRepositoryProvider.php
  - Services
    - MyService.php

App\Contracts\CustomModelInterface.php

<?php namespace App\Contracts;

interface CustomModelInterface {
    public function get();
}

App\Repositories\CustomModelRepository.php

<?php namespace App\Repositories;

use App\Contracts\CustomModelInterface;
use App\Models\CustomModel;

class CustomModelRepository implements CustomModelInterface {

    private $Model;

    public function __construct(CustomModel $model) {
        $this->Model = $model;
    }

    public function get() {
        return 'result';
    }
}

App\Services\MyService.php (Keep business logic / layer between controller and repositories)

<?php namespace App\Services;

use App\Contracts\CustomModelInterface;

class MyService {

    private $Model;

    public function __construct(CustomModelInterface $customModel) {
        $this->Model= $customModel;
    }

    public function getAll() {
        return $this->Model->get();
    }
}

App\Providers\AppRepositoryProvider.php

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppRepositoryProvider extends ServiceProvider {

    public function boot() {}

    public function register() {
        $models = array(
            'CustomModel'
        );

        foreach ($models as $idx => $model) {
            $this->app->bind("App\Contracts\{$model}Interface", "App\Repositories\{$model}Repository");
        }
    }
}

My controller looks like:

<?php namespace App\Http\Controllers;

use App\Services\MyService;

class SuperController extends Controller {

    private $My;

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

    public function getDetails() {
        return $this->My->getAll();
    }
}

composer.json

"autoload": {
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/",
            "App\\Models\\": "app/Models/",
            "App\\Contracts\\": "app/Contracts/",
            "App\\Repositories\\": "app/Repositories/"
        }
    },
like image 217
Andrew Kulakov Avatar asked Apr 17 '15 04:04

Andrew Kulakov


3 Answers

Thank you everyone, but problem was in my AppRepositoryProvider. As it's binding exception, then obviously the problem was with binding :)

Correct file is:

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppRepositoryProvider extends ServiceProvider {

    public function boot() {}

    public function register() {
        $models = array(
            'CustomModel',
            'CustomModel2',
            'CustomModel3'
        );

        foreach ($models as $model) {
            $this->app->bind("App\Contracts\\{$model}Interface", "App\Repositories\\{$model}Repository");
        }
    }
}

Note, that I'm using "App\Contracts\\{$model}Interface" (not escaping "{" symbol) and it generate correct string App\Contracts\CustomModelInterface instead of App\Contracts\{$model}Interface (with unexpected escaping).

like image 122
Andrew Kulakov Avatar answered Nov 05 '22 10:11

Andrew Kulakov


Every time I create a new repository/contract pair I make sure I do the following:

  1. check the classes used in the service provider (copy/paste the namespaces)
  2. register a new binding in config/app.php
  3. php artisan optimize

Many hours of useless debugging led me to this short checklist.

like image 55
Vlad Visinescu Avatar answered Nov 05 '22 10:11

Vlad Visinescu


For me, I forgot to bind in app->providers->RepositoryServiceProvider the repository like this in the register method

public function register()
{
    $this->app->bind(
        \App\Play\Contracts\PatientRepository::class,
        \App\Play\Modules\PatientModule::class
    );
}

Make sure your RepositoryServiceProvider is registered in AppServiceProvider.

public function register()
{   
    $this->app->register(RepositoryServiceProvider::class);
}
like image 17
Beulah Ana Avatar answered Nov 05 '22 09:11

Beulah Ana