如何在Laravel 5(5.2)中的另一个存储库类上注入存储库


How to inject a repository on another repository class in Laravel 5 (5.2)

假设我有两个实现契约的存储库(UserRepository、RoleRepository)(UserRepositoryInterface、RoleRepositoryInterface)。

我想做的是将RoleRepository注入UserRepository的构造函数方法中,我一直在努力实现这一点,但我遇到了以下错误:

生成[App''Http''Controllers''UserController]时,目标[App''Contracts''UserRepositoryInterface]不可实例化。

,这是我到目前为止得到的

composer.json

"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.2.*",
    "tymon/jwt-auth": "^0.5.9",
    "zizaco/entrust": "dev-laravel-5"
},
"require-dev": {
    "fzaninotto/faker": "~1.4",
    "mockery/mockery": "^0.9.4",
    "phpunit/phpunit": "~4.0",
    "symfony/css-selector": "2.8.*|3.0.*",
    "symfony/dom-crawler": "2.8.*|3.0.*"
},
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App''": "app/",
        "App''Models''": "app/Models/",
        "App''Contracts''": "app/Contracts/",
        "App''Repositories''": "app/Repositories/"
    }
},
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php",
        "tests/MockData.php"
    ]
}

config/app.php

'providers' => [
    /*
     * Laravel Framework Service Providers...
     */
    ...
    /**
     * Third-party Service Providers
     */
    ...
    /*
     * Application Service Providers...
     */
    ...
    /**
     * Custom Service Providers...
     */
    App'Providers'RepositoryServiceProvider::class,

app/Provider/RepositoryServiceProvider.php

namespace App'Providers;
use Illuminate'Support'ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
    public function register()
    {
        $models = [
            'Role',
            'User',
        ];
        foreach ($models as $model) {
            $this->app->bind(
                "App'Contracts''{$model}Interface",
                "App'Repositories''{$model}Repository"
            );
        }
    }
}

app/Controllers/UserController.php

<?php
namespace App'Http'Controllers;
use Illuminate'Http'Request;
use App'Http'Requests;
use App'Http'Controllers'Controller;
use App'Contracts'UserRepositoryInterface as UserRepository;
class UserController extends Controller
{
    /**
     * @var UserRepository
     */
    private $repo;
    /**
     * Class constructor
     *
     * @param UserRepository $repo
     */
    public function __construct(
        UserRepository $repo
    ) {
        $this->repo = $repo;
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  'Illuminate'Http'Request  $request
     *
     * @return 'Illuminate'Http'JsonResponse
     */
    public function store(Request $request)
    {
        $data = $request->all();
        $user = $this->repo->store($data);
        return response()->json($user, 201);
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  'Illuminate'Http'Request  $request
     * @param  int  $id
     *
     * @return 'Illuminate'Http'JsonResponse
     */
    public function update(Request $request, $id)
    {
        $data = $request->all();
        $user = $this->repo->store($data, $id);
        return response()->json($data, 200);
    }

app/Compacts/RoleRepositoryInterface.php

<?php
namespace App'Contracts;
interface RoleRepositoryInterface
{
    /**
     * Attach role to user
     *
     * @param  static $user
     * @param  string $roleName
     *
     * @return static
     */
    public function role($user, $roleName);
}

app/Compacts/UserRepositoryInterface.php

<?php
namespace App'Contracts;
interface UserRepositoryInterface
{
    /**
     * Create new or update an existing user
     *
     * @param  array  $data
     * @param  int    $id
     *
     * @return bool|int|array
     */
    public function store(array $data, $id = null);
}

app/Repositories/RoleRepository.php

<?php
namespace App'Repositories;
use InvalidArgumentException;
use App'Contracts'RoleRepositoryInterface;
use App'Models'Role;
class RoleRepository extends Role implements RoleRepositoryInterface
{
    /**
     * Attach a role to user
     *
     * @param  static $user
     * @param  string $roleName
     *
     * @return static
     *
     * @throws 'InvalidArgumentException
     */
    public function attachRole($user, $roleName)
    {
        if (!$user instanceof App'Models'User::class) {
            throw new InvalidArgumentException("{$user} must be an instance of App'Models'User");
        }
        // find role
        $role = $this->where('name', $roleName)->first();
        // attach role to user
        $user->attachRole($role);
        return $user;
    }
}

app/Repositories/UserRepository.php

<?php
namespace App'Repositories;
use App'Contracts'RoleRepositoryInterface as RoleRepository;
use App'Contracts'UserRepositoryInterface;
use App'Models'User;
class UserRepository extends User implements UserRepositoryInterface
{
    /**
     * @var RoleRepository
     */
    private $roleRepo;
    /**
     * Class constructor
     *
     * @param RoleRepository $roleRepo
     */
    public function __construct(RoleRepository $roleRepo)
    {
        $this->roleRepo = $roleRepo;
    }
    /**
     * Create new or update an existing user
     *
     * @param  array  $data
     * @param  int    $id
     *
     * @return bool|int|static
     */
    public function store(array $data, $id = null)
    {
        if (is_null($id)) {
            $user = $this->create($data);
            $userWithRole = $this->roleRepo->attachRole($user, $data['role']);
            return $user;
        } else {
            return $this->where('id', $id)
              ->update($data);
        }
    }
}

任何答案都将不胜感激。。。

我认为您的代码中有一个错误,特别是在RepositoryServiceProvider中。应该是:

foreach ($models as $model) {
        $this->app->bind(
            "App'Contracts''{$model}RepositoryInterface",
            "App'Repositories''{$model}Repository"
        );
}

注意:错误在串联中,您得到了"App'Contracts''{$model}Interface",但它应该是"App'Contracts''{$model}RepositoryInterface"