简体   繁体   中英

Injection in Repository

I found many questions about my problem and tried (I think) all the solutions, but I can not make it work. I'm overlooking something very easy, probably.

I'm using Laravel 5. I try to implement a repository-pattern. I have an Eloquent model '\\Notos\\Kind'.

Then I have this interface:

namespace Notos\Contracts;

interface Kind
{
    public function findByName($name);
}

My Repository looks like this:

namespace Notos\Repository;


use Illuminate\Database\Eloquent\Model;
use Notos\Contracts\Kind as KindContract;

class Kind implements KindContract
{
    protected $kind;

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

    public function findByName($name)
    {
        return $this->kind->firstOrCreate(array('name' => $name));
    }
}

My ServiceProvider:

namespace Notos\Providers;

use Illuminate\Support\ServiceProvider;
use Notos\Kind;
use Notos\Repository\Kind as KindRepository;


class RepoServiceProvider extends ServiceProvider
{

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('Notos\Contracts\Kind', function ($app) {
            return new KindRepository(new Kind);
        });
    }
}

And my controller that uses the repository:

namespace Notos\Http\Controllers;

use Notos\Repository\Kind as KindRepository;

class KindController extends Controller
{
    protected $kind;

    public function __construct(KindRepository $kind)
    {
        $this->kind = $kind;
    }

    public function find($name)
    {
        return $this->kind->findByName($name);
    }
}

This provider is registered in config/app.php

When I try to execute the KindController@find I get this error:

BindingResolutionException in Container.php line 785:
Target [Illuminate\Database\Eloquent\Model] is not instantiable.

I can't find what I'm doing wrong. It works perfect if I change __construct(Model $kind) to __construct(Kind $kind).

Any ideas? Thanks

The first thing, I would advice you to add to your class names the function so for example instead of Kind for repository use KindRepository , the same for contract. Otherwise you will have 3 kinds classes (of course in different namespaces) but it will be hard to analyse the code.

The problem here is that in your KindController you try to inject KindRepository directly but in constructor you use Model . It won't work because Model is only abstract class. What you should do to make it work?

In the code:

$this->app->bind('Notos\Contracts\Kind', function ($app) {
            return new KindRepository(new Kind);
        });

you told Laravel that when you will use Notos\\Contracts\\Kind it should create KindRepository for you with Kind in constructor - look you told here about Contract, not about repository itself.

So to make it work, you should use in your controller not your repository, but your contract.

Instead of line:

use Notos\Repository\Kind as KindRepository;

you should write:

use Notos\Contracts\Kind as KindRepository;

and it should work now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM