it-swarm.com.de

Laravel 5 - Schnittstelle ist nicht instanziierbar

Ich weiß, dass diese Frage so oft gestellt wurde, aber keine der Antworten hat mir geholfen.

Ich bekomme eine Ausnahme in Laravel 5

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

Was ich ohne Erfolg getan habe:

  • Registrieren Sie App\Providers\AppRepositoryProvider bei app.php-Providern
  • php artisan clear-compiled
  • Alles funktioniert, wenn ich Schnittstellen in Repositories in MyService ersetze, aber ich denke, dass es falsch ist (sollte es von IoC-Container behandelt werden?).

Struktur:

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 (Geschäftslogik/-schicht zwischen Controller und Repositorys beibehalten)

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

Mein Controller sieht so aus:

<?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
Andrew Kulakov

Vielen Dank an alle, aber das Problem lag in meinem AppRepositoryProvider. Als bindende Ausnahme war das Problem natürlich das Binden :)

Die korrekte Datei ist:

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

Beachten Sie, dass ich "App\Contracts\\{$model}Interface" verwende (nicht das Escape-Symbol "{") und es die richtige Zeichenfolge App\Contracts\CustomModelInterface anstelle von App\Contracts\{$model}Interface generiert (mit unerwarteter Escape-Funktion).

32
Andrew Kulakov

Jedes Mal, wenn ich ein neues Repository/Vertragspaar anlege, vergewissere ich mich, dass ich Folgendes mache: 

  1. Überprüfen Sie die im Service Provider verwendeten Klassen (kopieren Sie die Namespaces)
  2. registrieren Sie eine neue Bindung in der Datei config/app.php
  3. pHP Handwerker optimieren

Viele Stunden des nutzlosen Debuggens führten mich zu dieser kurzen Checkliste.

12
Vlad Visinescu

Für mich habe ich vergessen, app->providers->RepositoryServiceProvider Das Repository so in die register-Methode einzubinden

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

Stellen Sie sicher, dass Ihre RepositoryServiceProvider in AppServiceProvider registriert ist.

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

Ich bin an diesem Fehler vorbei gegangen:

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

Bezüglich:

Ziel ist nicht instanziierbar. Laravel 5 - App-Bindungsdienstanbieter

2
Connor Leech

Auf App\Services\MyService.php übergeben Sie diese Schnittstelle mit Abhängigkeitsinjektion, die versucht, das zu instanziieren - 

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

was falsch ist.

Versuchen Sie, das in dieser Klasse - class MyService implements CustomModelInterface { - zu implementieren und verwenden Sie die Funktion dieser Schnittstelle wie - 

$this->get();

Oder du benutzt es - class CustomModelRepository implements CustomModelInterface {

Also wenn du das tust - 

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

dann können Sie auch auf die Schnittstellenmethoden zugreifen.

2
Sougata Bose

Ich habe gerade ein ähnliches Problem erlebt, und der Grund für meinen Fehler war, dass ich $defer auf true in der Service-Provider-Klasse festgelegt hatte, aber die erforderliche provides()-Methode nicht implementiert hatte.

Wenn Sie die Erstellung Ihrer Klasse verschoben haben, bis sie benötigt wird und nicht eifrig geladen wird, müssen Sie auch die Methode provides implementieren, die einfach ein Array der vom Provider bereitgestellten Klassen zurückgibt. Ich glaube, dass es sich bei einer Schnittstelle um den Namen der Schnittstelle und nicht um die konkrete Klasse handeln sollte.

Z.B.

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

Aktuelle Dokumentation: https://laravel.com/docs/5.5/providers#deferred-providers

Ich hoffe, das hilft jemand anderem.

1
Kenny Body

Mach dir keine Sorgen, Jungs. Ich habe eine Lösung für dein Problem.

Ich habe ein Beispiel für dich.

Schritt1: php handwerklich machen: Repository Repository/Post // Durch Hinzufügen dieses Befehls können Sie ein Repository und eloquente Dateien erstellen

Schritt 2: Nachdem Sie diese Datei hinzugefügt haben, müssen Sie dieses Repository in dem Controller hinzufügen/verwenden, in dem Sie verwenden möchten.

zum Beispiel: App\Repositories\Contracts\PostRepository verwenden;

Schritt 3: Nach dem Hinzufügen dieses Repos in Ihrem Controller wird beim Ausführen der App eine Fehlermeldung wie "Schnittstelle ist nicht instanziierbar" angezeigt. Es kommt daher, dass Sie ein Repo erstellt und in einem Controller verwendet haben, aber Laravel weiß nicht, wo dieses Repository registriert ist, und bindet sich mit welchem ​​Eloquenten. Damit wirft es einen Fehler.

Schritt 4: Um diesen Fehler zu beheben, müssen Sie Ihr Repo mit Ihrem Redner in AppServiceProvider verbinden. Z.B: 

AppServiceProvider.php-Datei

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

Schritt 5: Nach dem Binden von Repo und Eloquent können Sie alle Repo-Methoden in Ihrem Controller verwenden. Genießen.....

Bitte lassen Sie mich wissen, wenn Sie Fragen haben.

1
Umang Soni

Als letztes müssen Sie die Schnittstelle verwenden, die Sie an das Repository gebunden haben. 

Richten Sie es ein und führen Sie Ihre Laravel-App aus, um sicherzustellen, dass Sie keine Fehler erhalten. 

In meinem Fall hatte ich ein Missverhältnis zwischen meinem Repository und der Schnittstelle.

interface UserRepositoryInterface{
  public function get($userId); 
}

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

Wie Sie sehen, enthält die get-Methode der Schnittstelle keinen Typhinweis, aber die get-Methode der UserRepository-Klasse verfügt über einen Typhinweis.

Sie erhalten diese Fehlermeldung nicht, wenn Sie Ihre Schnittstellenbindung sofort verwenden.

0
Adam Winnipass

Ich denke, das Problem hier ist, dass Sie App\Contracts\CustomModelInterface nicht an irgendetwas binden, also versucht Laravel, eine Instanz der Schnittstelle zu erstellen.

In App\Providers\AppRepositoryProvider.php haben Sie nur:

$models = array(
            'Model'
        );

sie sollten jedoch CustomModel in diesem Array haben, also sollte es so aussehen:

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

Beachten Sie, dass dies auch dadurch verursacht werden kann, dass der _constructor für die Klasse als privat deklariert wird oder anderweitig blockiert ist .... Wenn der Konstruktor nicht aufgerufen werden kann, schlägt die Bindung fehl

0
Lea de Groot