services register providers container app php laravel repository-pattern laravel-5 laravel-ioc

php - providers - register service laravel



Laravel 5: la interfaz no es instanciable (8)

Cada vez que creo un nuevo par de repositorio / contrato, me aseguro de hacer lo siguiente:

  1. verifique las clases utilizadas en el proveedor de servicios (copiar / pegar los espacios de nombres)
  2. registrar un nuevo enlace en config / app.php
  3. php artesanal optimizar

Muchas horas de depuración inútil me llevaron a esta breve lista de verificación.

Sé que esta pregunta fue hecha muchas veces, pero ninguna de las respuestas me ayudó.

Estoy recibiendo una excepción en Laravel 5

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

Lo que he hecho sin éxito:

  • Registrar App/Providers/AppRepositoryProvider en proveedores de app.php
  • php artisan clear-compiled
  • Todo funciona si reemplazo interfaces en repositorios en MyService, pero creo que está mal (¿debería ser manejado por el contenedor de IoC?).

Estructura:

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

Aplicación / 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 (Mantener la lógica / capa de negocios entre el controlador y los repositorios)

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

Mi controlador se ve así:

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


Creo que el problema aquí es que no vincula App/Contracts/CustomModelInterface a nada, por lo que Laravel intenta crear una instancia de interfaz.

En App/Providers/AppRepositoryProvider.php solo tiene:

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

pero también debería tener en este arreglo CustomModel , así que debería verse así:

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


En App/Services/MyService.php está pasando esa interfaz con la inyección de dependencia que intenta crear una instancia de eso:

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

Cuál está mal.

Intenta implementar eso en esa clase - class MyService implements CustomModelInterface { y usa la función de esa interfaz como -

$this->get();

O lo está usando - class CustomModelRepository implements CustomModelInterface {

Entonces si lo haces -

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

entonces también puedes acceder a los métodos de interfaz.


Gracias a todos, pero el problema estaba en mi AppRepositoryProvider. Como es una excepción vinculante, obviamente el problema fue con el enlace :)

El archivo correcto es:

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

Tenga en cuenta que estoy usando la "App/Contracts//{$model}Interface" (que no escapa del "{" símbolo) y genera la cadena correcta App/Contracts/CustomModelInterface lugar de App/Contracts/{$model}Interface (con escapando inesperadamente).


Lo último que debe hacer es usar la interfaz que enlazó al repositorio.

Configúralo e intenta ejecutar tu aplicación laravel para asegurarte de que no obtienes ningún error.

En mi caso, tuve un desajuste entre mi repositorio y la interfaz.

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

Como puede ver, el método get de interfaz no incluye una sugerencia de tipo, pero el método get de la clase UserRepository tiene una sugerencia de tipo.

No obtendrá este error si inmediatamente comienza a usar su enlace de interfaz.


Para mí, olvidé vincular en la app->providers->RepositoryServiceProvider el repositorio como este en el método de registro

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

Asegúrese de que su RepositoryServiceProvide esté registrada en AppServiceProvider .

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



Tenga en cuenta que esto también puede ser causado por _constructor en la clase que se declara privada, o que de otro modo está siendo bloqueada ... Si no puede llamar al constructor, el enlace fallará