Laravel 5 – Интерфейс не работает

Я знаю, что этот вопрос задавали так много раз, но ни один из ответов не помог мне.

Я получаю исключение в Laravel 5

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

То, что я сделал без успеха:

  • Зарегистрировать App\Providers\AppRepositoryProvider в app.php провайдерах
  • php artisan clear-compiled
  • Все работает, если я заменяю интерфейсы на репозитории в MyService, но я чувствую, что это неправильно (нужно ли это обрабатывать контейнером IoC?).

Буду признателен за любую помощь.

ОБНОВЛЕНИЕ: Я решил проблему (см. Мой ответ ниже ) Спасибо всем.

Состав:

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

App \ Контракты \ CustomModelInterface.php

 <?php namespace App\Contracts; interface CustomModelInterface { public function get(); } 

App \ Хранилища \ 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 (Держите бизнес-логику / уровень между контроллером и репозиториями)

 <?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"); } } } 

Мой контроллер выглядит так:

 <?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/" } }, 

    Спасибо всем, но проблема была в моем AppRepositoryProvider. Поскольку это обязательное исключение, то, очевидно, проблема заключалась в привязке 🙂

    Правильный файл:

     <?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"); } } } 

    Обратите внимание, что я использую "App\Contracts\\{$model}Interface" (не экранирующий «{» символ), и он генерирует правильную строку App\Contracts\CustomModelInterface вместо App\Contracts\{$model}Interface (с неожиданное ускорение).

    каждый раз, когда я создаю новую пару репозитория / контракта, я делаю следующее:

    1. проверьте классы, используемые в поставщике услуг (скопируйте / вставьте пространства имен)
    2. зарегистрировать новое связывание в config / app.php
    3. Оптимизировать php-artisan

    Много часов бесполезной отладки привели меня к этому короткому контрольному списку.

    Надеюсь, это поможет кому-то. Ура!

    В App\Services\MyService.php вы передаете этот интерфейс с инъекцией зависимостей, которая пытается создать это –

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

    что неправильно.

    Попробуйте реализовать, что в этом классе – class MyService implements CustomModelInterface { и использует функцию этого интерфейса, например –

     $this->get(); 

    Или вы используете его – class CustomModelRepository implements CustomModelInterface {

    Так что если вы это сделаете –

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

    то вы также можете получить доступ к методам интерфейса.

    Я думаю, проблема в том, что вы не привязываете App\Contracts\CustomModelInterface ко всему, что Laravel пытается создать экземпляр интерфейса.

    В App\Providers\AppRepositoryProvider.php вас есть только:

     $models = array( 'Model' ); 

    но вы также должны иметь в этом массиве CustomModel , поэтому он должен выглядеть так:

     $models = array( 'Model', 'CustomModel', ); 

    Обратите внимание, что это также может быть вызвано _constructor при объявлении класса приватным или в противном случае блокируется … Если он не может вызвать конструктор, привязка не удастся

    Последнее, что вы делаете, это использовать интерфейс, который вы привязали к репозиторию.

    Установите его и попробуйте запустить приложение laravel, чтобы убедиться, что у вас нет ошибок.

    В моем случае у меня было несоответствие между моим репозиторием и интерфейсом.

     inteface UserRepositoryInterface{ public function get($userId); } class UserRepository implements UserRepositoryInterface{ public function get(int $userId); } 

    Как вы видите, метод get интерфейса не включает подсказку типа, но метод getReadository класса UserRepository имеет тип подсказки.

    Вы не получите эту ошибку, если сразу начнете использовать привязку интерфейса.

    Для меня я забыл связать в app->providers->RepositoryServiceProvider репозиторий, подобный этому, в методе register

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

    убедитесь, что ваш RepositoryServiceProvide r зарегистрирован в AppServiceProvider .

     public function register() { $this->app->register(RepositoryServiceProvider::class); } 

    надеюсь, что это помогает кому-то.