Laravel Target [App\Repositories\〇〇[BInterface] is not instantiable while buildingのエラーが出た

# 目的

- エラー「Target [App\Repositories\リポジトリインターフェースファイル名] is not instantiable while building 」のエラーが出て解決した話をまとめる

# is not instantiable while building系のエラーの大体の原因

- 筆者が経験した当該エラーでの問題箇所の代替がtypoやbindのミスであった。
- use宣言部分、関係しそうなファイルのnamespace部分、ファイル名とclassの部分が一致しているか、bindの方法は間違っていないかを今一度確認していただきたい。
- サービスファイル、リポジトリインターフェースファイル、リポジトリファイルは`$ php artisan`コマンドで作成できない。（はず）
- 手打ちの部分が多くなると自分のような初心者だとtypoや記載ミスが多発するのでゆっくり落ち着いて再確認してみよう。

# エラー内容

- DBアクセス処理をサービスとリポジトリに分割していざブラウザで確認使用としてたところ下記のエラーが発生した。

    ```error
    Target [App\Repositories\ContentRepositoryInterface] is not instantiable while building [App\Http\Controllers\ContentController, App\Services\ContentService].
    ```

# 関連ファイルの内容

- /app/Http/Controllers/ContentController.php

    ```laravel_crud/app/Http/Controllers/ContentController.php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Models\Content;
    use App\Http\Requests\ContentRequest;
    // 下記を追記する
    use App\Services\ContentService;
    
    class ContentController extends Controller
    {
        // 下記を追記する
        private $contentService;
    
        public function __construct(ContentService $contentService)
        {
            $this->contentService = $contentService;
        }
        // 上記までを追記する
    
        public function input()
        {
            return view('contents.input');
        }
    
        public function save(ContentRequest $contentRequest)
        {
            $input_content = new Content();
            $input_content->content = $contentRequest['content'];
            $input_content->save();
            
            return redirect('/output');
        }
    
        public function output()
        {
            // 下記を修正する
            $all_contents = $this->contentService->getContent();
            
            return view('contents.output', [
                'all_contents' => $all_contents,
            ]);
        }
    
        public function delete(Request $request)
        {
            $contents_delete_query = Content::select('*');
            $contents_delete_query->where('id', $request['content_id']);
            $contents_delete_query->delete();
    
            return redirect('/output');
        }
    
        public function edit($content_id)
        {
            $edit_contents = $this->contentService->getEditContent($content_id);
            $edit_content = $edit_contents[0];
    
            return view('contents.edit', [
                'edit_content' => $edit_content,
            ]);
        }
    
        public function update(ContentRequest $contentRequest)
        {
            $contents_update_query = Content::select('*');
            $contents_update_query->where('id', $contentRequest['content_id']);
            $update_contents = $contents_update_query->get();
    
            $update_content = $update_contents[0];
            $update_content->content = $contentRequest['content'];
            $update_content->save();
    
            return redirect('/output');
        }
    }
    ```
- app/Services/ContentService.php

    ```laravel_crud/app/Services/ContentService.php
    <?php

    namespace App\Services;
    
    use App\Models\Content;
    use App\Repositories\ContentRepositoryInterface;
    
    class ContentService
    {
        public function __construct(ContentRepositoryInterface $contentRepositoryInterface)
        {
            $this->contentRepositoryInterface = $contentRepositoryInterface;
        }
    
        public function getContent(){
            return $this->contentRepositoryInterface->getContent();
        }
    
        public function getEditContent($content_id){
            return $this->contentRepositoryInterface->getEditContent($content_id);
        }
    }
    ```
- app/Repositories/ContentRepositoryInterface.php

    ```laravel_crud/app/Repositories/ContentRepositoryInterface.php
    <?php

    namespace App\Repositories;
    
    interface ContentRepositoryInterface
    {
        public function getContent();
    
        public function getEditContent($content_id);
    }
    ```
- app/Repositories/ContentRepository.php

    ```laravel_crud/app/Repositories/ContentRepository.php
    <?php
    
    namespace App\Repositories;
    
    use App\Models\Content;
    
    class ContentRepository implements ContentRepositoryInterface
    {
        public function getContent(){
            $contents_get_query = Content::select('*');
            return $contents_get_query->get();
        }
    
        public function getEditContent($content_id){
            $contents_edit_query = Content::select('*');
            $contents_edit_query->where('id', $content_id);
            return $contents_edit_query->get();
        }
    }
    ```
- app/Providers/AppServiceProvider.php

    ```laravel_crud/app/Providers/AppServiceProvider.php
    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //下記を追記する
            $this->app->bind(
            );
        }
    
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            //
        }
    }
    ```

# エラー原因

- app/Providers/AppServiceProvider.phpのbindの記載に誤りがあった。下記に記載ミス部分を抜粋して記載する。

    ```app/Providers/AppServiceProvider.php
    $this->app->bind(
        App\Repositories\ContentRepositoryInterface::class,
        App\Repositories\ContentRepository::class
    );
    ```
- リポジトリインターフェースとリポジトリのbind登録部分の頭に`\`が記載されておらずbindができていなかった。
- 正常なbindの方法を下記に記載する。

    ```app/Providers/AppServiceProvider.php
    $this->app->bind(
        \App\Repositories\ContentRepositoryInterface::class,
        \App\Repositories\ContentRepository::class
    );
    ```
- 正常なAppServiceProvider.phpの全記載内容を下記に記載する。

    ```laravel_crud/app/Providers/AppServiceProvider.php
    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //下記を追記する
            $this->app->bind(
                \App\Repositories\ContentRepositoryInterface::class,
                \App\Repositories\ContentRepository::class
            );
        }
    
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            //
        }
    }
    ```

# 追記（2022/07/15）

- laravel9でも同様の内容でエラーが出た。
- 当該のエラーはリポジトリサービスプロバイダーにてリポジトリインターフェースとリポジトリが紐付いていなかったために発生した。
- 下記のようなエラーが出た。

    ```
    Target Aクラス名 is not instantiable while building Bクラス名
    ```

- 「Bクラスの構築中にAクラスのインスタンス化に失敗しました」というエラーだった。
    
# 参考文献

- [【Laravel】リポジトリパターン実装におけるエラー Target [App\Repositories\UserRepositoryInterface] is not instantiable while building](https://qiita.com/antk/items/38971fba1de4e6872b82)