LoginSignup
8
7

More than 3 years have passed since last update.

【Laravel】リポジトリパターン実装におけるエラー Target [App\Repositories\UserRepositoryInterface] is not instantiable while building

Last updated at Posted at 2020-08-04

3行で

  • Userリポジトリが読み込めない
  • なぜか他のリポジトリは読める(例えばArticlesRepositoryとか)
  • AppServiceProvider.php を見直す

概要

「マイページにユーザーが投稿した記事を、ユーザー名に基づいてArticlesテーブルから持ってくる」というパターンで実装する

リポジトリパターン実装における各ファイル

実装クラス

UserRepository.php
<?php

namespace App\Repositories\User;

// Modelディレクトリを作るパターンで実装している
use App\Models\User;

class UserRepository implements UserRepositoryInterface
{
  protected $user;

    /**
    * @param object $user
    */

  public function __construct(User $user)
  {
      $this->user = $user;
  }

  public function getUser($name)
  {
    return $this->user->where('name', $name)->first();
  }
}

インターフェース

UserRepositoryInterface.php
<?php

namespace App\Repositories\User;

interface UserRepositoryInterface
{
    public function getUser($name);
}

コントローラ

UserController.php
<?php

namespace App\Http\Controllers;
use App\Repositories\User\UserRepositoryInterface;

use App\Models\User;
use Illuminate\Http\Request;

class UserController extends Controller
{    
    protected $user;

    public function __construct(UserRepositoryInterface $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function show(String $name)
    {
        $user = $this->userRepository->getUser($name);

        $articles = $user->articles->sortByDesc('create_at');

        return view('users.show', [
            'user' => $user,
            'articles' => $articles,
        ]);
    }
}

サービスプロバイダ

下記のコードでエラーが起きた。

AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */

    /**
     * Bootstrap any application services.
     *
     * @return void
     */

    public function boot()
    {
        //
    }

    // インターフェースと実装クラスを登録
    public function register()
    {
        $this->app->bind(
            \App\Repositories\Article\ArticleRepositoryInterface::class,
            \App\Repositories\Article\ArticleRepository::class,
            \App\Repositories\User\UserRepositoryInterface::class,
            \App\Repositories\User\UserRepository::class
        );
    }
}

これが問題だったが、自分の知る限り(あと調べた限り)ではこのパターンで実装できている。
3日くらい悩んだりいろいろ試してたらこの記事を見つけた。

Target [App\Interfaces\User\UserInterface] is not instantiable while building #1

試しに修正してみる。↓

AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */

    /**
     * Bootstrap any application services.
     *
     * @return void
     */

    public function boot()
    {
        //
    }

    // インターフェースと実装クラスを登録
    public function register()
    {
        $this->app->bind(
            \App\Repositories\Article\ArticleRepositoryInterface::class,
            \App\Repositories\Article\ArticleRepository::class
        );
        $this->app->bind(
            \App\Repositories\User\UserRepositoryInterface::class,
            \App\Repositories\User\UserRepository::class
        );
    }
}

そしたら直った。
理由が正直わからないのでもしわかる方がいたら教えてください。

教えていただきました(コメント欄参照)。

8
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7