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

37

Решение

Спасибо всем, но проблема была в моем 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 (с неожиданным побегом).

32

Другие решения

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

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

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

12

Для меня я забыл связать в app->providers->RepositoryServiceProvider
хранилище, как это в методе регистра

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

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

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

На 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;
}

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

2

Я прошел эту ошибку:

php artisan config:clear
php artisan clear-compiled
php artisan optimize
php artisan config:cache

Относится к:

Цель не является инстанцируемой. Laravel 5 — поставщик услуг привязки приложений

2

Я только что столкнулся с проблемой, похожей на эту, и причиной моей ошибки было то, что я установил $defer в true в классе поставщика услуг, но я не реализовал требуемый provides() метод.

Если вы отложили создание своего класса до тех пор, пока он не будет необходим, а не загружен с нетерпением, то вам также необходимо реализовать provides метод, который должен просто возвращать массив классов, которые предоставляет провайдер. Я полагаю, что в случае интерфейса это должно быть имя интерфейса, а не конкретный класс.

Например.

public method provides(): array
{
return [
MyInterface::class,
];
}

Текущая документация: https://laravel.com/docs/5.5/providers#deferred-providers

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

1

Не волнуйтесь, ребята. У меня есть решение вашей проблемы.

У меня есть пример для вас.

Шаг 1: php artisan make: репозиторий Репозиторий / Пост // Добавив эту команду, вы можете создать репозиторий и красноречивые файлы

Шаг 2: После добавления этого файла вы должны добавить / использовать этот репозиторий в контроллере, в котором вы хотите использовать.

например: использовать App \ Repositories \ Contracts \ PostRepository;

Шаг 3: После добавления этого репозитория в ваш контроллер, если вы запустите приложение, вы получите сообщение об ошибке «Интерфейс не создается». Это происходит потому, что вы создали репо и используете его в контроллере, но laravel не знает, где этот репозиторий зарегистрирован и с каким красноречивым связыванием. Так что это выдает ошибку.

Шаг 4: Чтобы устранить эту ошибку, вы должны связать репозиторий с вашим красноречивым в AppServiceProvider.
Например:

Файл AppServiceProvider.php

<?php
namespace App\Providers;

// **Make sure that your repo file path and eloquent path must be correct.**

use App\Repositories\Contracts\PostRepository;         // **Use your repository here**

use App\Repositories\Eloquent\EloquentPostRepository;  **// Use your eloquent here**

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*
* @return void
*/
public function register() {

**// And bind your repository and eloquent here. **

$this->app->bind(PostRepository::class, EloquentPostRepository::class);
}
}

Шаг 5: После привязки репо и красноречивых вы можете использовать все методы репо в вашем контроллере. Наслаждаться…..

Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы.

1

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

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

$models = array(
'Model'
);

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

$models = array(
'Model',
'CustomModel',
);
0
По вопросам рекламы [email protected]