web-dev-qa-db-ja.com

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\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(ビジネスロジック/コントローラーとリポジトリの間のレイヤーを保持)

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

みなさん、ありがとうございますが、問題は私の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を生成していることに注意してください。

39
Andrew Kulakov

新しいリポジトリ/契約のペアを作成するたびに、次のことを確認します。

  1. サービスプロバイダーで使用されているクラスを確認する(名前空間をコピー/貼り付け)
  2. config/app.phpに新しいバインディングを登録します
  3. pHPアーティザン最適化

無駄なデバッグに何時間も費やしたため、この短いチェックリストにたどり着きました。

19
Vlad Visinescu

私にとっては、app->providers->RepositoryServiceProviderでregisterメソッドでこのようなリポジトリをバインドするのを忘れていました

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

RepositoryServiceProviderがAppServiceProviderに登録されていることを確認してください。

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

私はこのエラーを実行し過ぎました:

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

関連する:

ターゲットはインスタンス化できません。Laravel 5-アプリバインディングサービスプロバイダー

5
Connor Leech

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
Sougata Bose

これに似た問題が発生したばかりで、エラーの原因は、サービスプロバイダークラスで$defertrueに設定したが、必要なprovides()メソッドを実装していなかったことです。

クラスの作成を熱心にロードするのではなく、必要になるまで延期した場合は、プロバイダーが提供するクラスの配列を返すだけのprovidesメソッドも実装する必要があります。インターフェイスの場合、具体的なクラスではなく、インターフェイスの名前である必要があります。

例えば。

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

現在のドキュメント: https://laravel.com/docs/5.5/providers#deferred-providers

これが他の人の助けになることを願っています。

1
Kenny Body

みんな心配しないで。あなたの問題の解決策があります。

私はあなたのための例を持っています。

ステップ1:php artisan make:repository Repository/Post //このコマンドを追加することで、リポジトリと雄弁なファイルを作成できます

ステップ2:そのファイルを追加した後、使用するコントローラーでこのリポジトリを追加/使用する必要があります。

例:se 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
Umang Soni

最後に行うことは、リポジトリにバインドしたインターフェイスを使用することです。

それを設定し、laravelアプリを実行して、エラーが発生しないことを確認してください。

私の場合、リポジトリとインターフェイスが一致していません。

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

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

ご覧のとおり、インターフェイスのgetメソッドにはタイプヒントは含まれていませんが、UserRepositoryクラスのgetメソッドにはタイプヒントがあります。

インターフェイスバインディングの使用をすぐに開始した場合、このエラーは発生しません。

0
Adam Winnipass

ここでの問題は、Laravelがインターフェイスのインスタンスを作成しようとするので、App\Contracts\CustomModelInterfaceを何にもバインドしないことだと思います。

App\Providers\AppRepositoryProvider.phpには次のものしかありません:

$models = array(
            'Model'
        );

ただし、この配列にはCustomModelも含める必要があるため、次のようになります。

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

これは、プライベートとして宣言されているクラスの_constructor、またはブロックされていることによっても発生する可能性があることに注意してください...コンストラクタを呼び出せない場合、バインディングは失敗します

0
Lea de Groot