Andrés Kulakov
Sé que esta pregunta se hizo tantas 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:
- Registro
App\Providers\AppRepositoryProvider
enapp.php
proveedores php artisan clear-compiled
- Todo funciona si reemplazo las interfaces en los repositorios en MyService, pero siento que está mal (¿debería ser manejado por el contenedor IoC?).
Estructura:
app
- Contracts
- CustomModelInterface.php
- Models
- CustomModel.php
- Repositories
- CustomModelRepository.php
- Providers
- AppRepositoryProvider.php
- Services
- MyService.php
Aplicación\Contratos\CustomModelInterface.php
<?php namespace App\Contracts;
interface CustomModelInterface {
public function get();
}
Aplicación\Repositorios\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 comercial/capa 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 parece a:
<?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();
}
}
compositor.json
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"App\\Models\\": "app/Models/",
"App\\Contracts\\": "app/Contracts/",
"App\\Repositories\\": "app/Repositories/"
}
},
Vlad Visinescu
Cada vez que creo un nuevo par de repositorio/contrato, me aseguro de hacer lo siguiente:
- comprobar las clases utilizadas en el proveedor de servicios (copiar/pegar los espacios de nombres)
- registrar un nuevo enlace en config/app.php
- optimización artesanal de php
Muchas horas de depuración inútil me llevaron a esta breve lista de verificación.
-
Olvidé el #2, me salvó
– Fasna
31 de octubre de 2017 a las 10:29
-
¡A mí también me faltaba el número 2! Actualicé de Laravel 4 a 5 y necesitaba registrar explícitamente mis proveedores personalizados en config/app.php junto con los proveedores de servicios predeterminados.
–Rick Gladwin
3 de junio de 2019 a las 2:16
-
Tuve que ejecutar php artesanal config:cache
– Máx.
22 de diciembre de 2020 a las 14:44
Andrés Kulakov
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 "App\Contracts\\{$model}Interface"
(sin escapar del símbolo “{“) y genera la cadena correcta App\Contracts\CustomModelInterface
en vez de App\Contracts\{$model}Interface
(con escape inesperado).
-
Si no me equivoco, acabas de saltar
interface
ahora, porque ahora después de la vinculación que ha utilizado, cada vez que llamainterface
un objeto derepository
se resolverá… y no la interfaz, no has usado elSoC
patrón de diseño de la forma en que debe ser… Suinterface
Los archivos ahora son inútiles. Corrígeme si estoy equivocado.– Hamza Uaghad
15 de julio de 2015 a las 17:15
-
¿Puedes explicar por qué usas
App\Contracts\\{$model}Interface
y no usarApp\Contracts\{$model}Interface
¿qué significa la doble barra invertida?– tdycss
7 de febrero de 2020 a las 17:13
-
@tdycss la primera barra invertida es parte del espacio de nombres, la segunda para escapar del
{
– sin el escape, terminas con el {} en el espacio de nombres resultante, que no existe en este caso. consulte también la nota debajo del ejemplo de código en la respuesta. Espero que ayude (:– Sandra
9 de junio de 2021 a las 11:29
Beulah Ana
Para mí, olvidé enlazar app->providers->RepositoryServiceProvider
el repositorio así 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
r está registrado en AppServiceProvider
.
public function register()
{
$this->app->register(RepositoryServiceProvider::class);
}
-
Este fue mi error. ¡Gracias!
– Carlos
20 de septiembre de 2018 a las 16:08
-
¡Suena bien! Gracias
– LuizEduardoMPF
3 mayo 2019 a las 13:32
-
Por alguna razón, esto solucionó mi problema a pesar de que había agregado el archivo a config/app.php. Registré el proveedor en register(), ejecuté config:cache, eliminé la línea en register() y las cachés subsiguientes tuvieron éxito.
– Máx.
4 de febrero de 2021 a las 14:52
Superé este error al ejecutar:
php artisan config:clear
php artisan clear-compiled
php artisan optimize
php artisan config:cache
Relacionado con:
Target no es instanciable. Laravel 5: proveedor de servicios de enlace de aplicaciones
El problema se resuelve agregando su repositorio en app/providers/AppServiceProvider como en el ejemplo a continuación.
public function register()
{
$this->app->singleton(UserRepository::class, EloquentUser::class);
}
No olvides el espacio de nombres
use Test\Repositories\EloquentUser;
use Test\Repositories\UserRepository;
funcionó para mí
Sougata Bosé
En App\Services\MyService.php
está pasando esa interfaz con inyección de dependencia que intenta instanciar eso:
public function __construct(CustomModelInterface $customModel) {
$this->Model= $customModel;
}
Cuál está mal.
Intenta implementar eso en esa clase – class MyService implements CustomModelInterface {
y use la función de esa interfaz como –
$this->get();
O lo estás usando – class CustomModelRepository implements CustomModelInterface {
Así que si lo haces –
public function __construct(CustomModelRepository $customModel) {
$this->Model= $customModel;
}
entonces también puede acceder a los métodos de la interfaz.
Acabo de experimentar un problema similar a este y la causa de mi error fue que había configurado $defer
a true
en la clase de proveedor de servicios pero no había implementado el requerido provides()
método.
Si ha aplazado la creación de su clase hasta que sea necesaria en lugar de cargarla con entusiasmo, entonces también debe implementar el provides
método que simplemente debería devolver una matriz de las clases que proporciona el proveedor. En el caso de una interfaz, creo que debería ser el nombre de la interfaz en lugar de la clase concreta.
P.ej
public method provides(): array
{
return [
MyInterface::class,
];
}
Documentación actual: https://laravel.com/docs/5.5/providers#deferred-providers
Espero que esto ayude a alguien más.
-
Correcto. Además, no olvide ejecutar “compositor dump-autoload” después.
– Ali Bakhshandeh
9 dic 2021 a las 21:42
Hoy encontré esta pregunta porque recibí el mismo mensaje de error. En mi caso, en mi ServiceProvider, tenía la propiedad
$defer = true;
Esto conduce al mismo error. Si encuentra el mismo problema, simplemente elimine la propiedad.– Bart McLeod
12 de abril de 2016 a las 7:18