Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RobertBaelde's avatar

Repository injection in Lumen

Hey guys,

I'm trying to inject a repository in to an Lumen controller. But it throws an error that the class does not exists.

My controller looks like this:

use App\Http\Controllers\Controller;
use App\Repositories\WebshopRepository as WebshopRepository;

class ApiController extends Controller {

   /**
    * The webshop repository instance.
    */
   protected $webshop;

   /**
    * Create a new controller instance.
    *
    * @param  WebshopRepository $webshop
    * @return void
    */
   public function __construct(WebshopRepository $webshop)
   {
       $this->webshop = $webshop;
   }

I think i need to register it using

 $app->bind('WebshopRepository', function($app) {
        return new WebshopRepository();
        });

But that doesn't work.

Does somebody have an example of how to do this properly?

0 likes
23 replies
bobbybouwmann's avatar

You need to do it like this (in a ServiceProvider)

public function register() 
{
    $this->app->bind(WebshopRepository::class, EloquentWebshopRepository::class);
}

Here is WebshopRepository the interface and EloquentWebshopRepository the used repository in your controller.

I also noticed that this doesn't make any sence

use App\Repositories\WebshopRepository as WebshopRepository;
1 like
RobertBaelde's avatar

Thanks for the answer. I figured that i forgot the namespace in the repository. When i added namespace App\Repositories;, the controller loaded the repository, but i couldn't use any other classes in the repository. However when i removed use App\Repositories\WebshopRepository as WebshopRepository;, it generates the old error, that the class does not exists.

When i try to implement @blackbird solution, it fails, and i get the class does not exists error. So i think it still isn't registered. But i can't figure out whats wrong..

My composer file looks like this, maybe there's something wrong with the loading of the repository folder?

{
    "name": "laravel/lumen",
    "description": "The Laravel Lumen Framework.",
    "keywords": ["framework", "laravel", "lumen"],
    "license": "MIT",
    "type": "project",
    "require": {
        "laravel/lumen-framework": "5.0.*",
        "vlucas/phpdotenv": "~1.0"
    },
    "require-dev": {
        "phpunit/phpunit": "~4.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/",
            "app/models/",
            "app/Repositories/"
        ]
    },
    "autoload-dev": {
        "classmap": [
            "tests/"
        ]
    },
    "config": {
        "preferred-install": "dist"
    }
}

Sorry if it's a stupid question, but i'm really confused with the loading in Lumen at the moment...

bobbybouwmann's avatar

I think you still need to register the service provider

http://lumen.laravel.com/docs/providers#registering-providers

So you probably have something like this app\Providers\DatabaseServiceProvider.php

use App\Repositories\WebshopRepository;
use App\Repositories\EloquentWebshopRepository;

class DatabaseServiceProvider extends ServiceProvider {

    public function register() 
    {
        $this->app->bind(WebshopRepository::class, EloquentWebshopRepository::class);
    }

}

And now in your app.php you add this

$app->register('App\Providers\DatabaseServiceProvider');
arabsight's avatar

you don't need to register a concrete class, only if you're using interfaces. plus why are you defining "app/Repositories/" in composer, you're using psr4. "App\Repositories*" gets auto-loaded. maybe you just have a typo somewhere.

bobbybouwmann's avatar

@arabsight It's common practice to you interfaces ;) The problem is not autoloading, the application just doesn't know where to find the correct implementation.

arabsight's avatar

@blackbird, he is not using interfaces, no need for registering a concrete class it gets auto loaded by the IoC container. I think he is not name-spacing his repositories, that's why he gets the error.

RobertBaelde's avatar

@blackbird I had the provider registered in the app.php file. So that's not the problem i guess. I checked and the register function is called. The strange thing is that the controller looks for the class in the controller folder. Class App\Http\Controllers\WebshopRepositoryInterface does not exist.

(i named the interface WebshopRepositoryInterface), my serviceprovider looks like this:

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Repositories\WebshopRepository;
use App\Repositories\WebshopRepositoryInterface;

class WebshopServiceProvider extends ServiceProvider
{

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
          $this->app->bind(WebshopRepository::class, WebshopRepositoryInterface::class);
    }
}

@arabsight I removed the app/Repositories from composer. It was one of my many attempts to get it working.

arabsight's avatar

add namespace App\Repositories; to your repositories and remove the registration unless you're using interfaces

bobbybouwmann's avatar

The namespace is not correct. Update the namespace in your interface to this

<?php namespace App\Repositories;
RobertBaelde's avatar

That namespace was already in the interface. So that's not the problem unfortunately.

RobertBaelde's avatar

WebshopRepositoryInterface

<?php 
namespace App\Repositories;

interface WebshopRepositoryInterface {

    public function test($test);
    public function loadEvents($key);
    public function loadTickets($key, $event_id);
    public function checktickets($key, $data);
    public function validate_fields($key, $event_id, $input);
    public function dopay($key, $input);
    public function paymentstatus($transaction_id);
    public function loadtransactiontickets($transaction_id);
    public function downloadticket($key, $ticket_id, $transaction_id);

}

WebshopRepository

<?php
namespace App\Repositories;

class WebshopRepository {

    // load all upcoming events from the shop
    public function loadEvents($key){
       // check if the shop is in cache
        if (!Cache::has($key.'_events'))
        {
            // load shop
            $shop = Shop::where('key', $key)->where('type', 'online')->first();
         //etc etc...
arabsight's avatar
Level 10

you're not implementing the interface:

class WebshopRepository implements WebshopRepositoryInterface

in the controller inject the interface not the concrete class:

<?php namespace App\Http\Controllers;
use App\Repositories\WebshopRepositoryInterface;

class ApiController extends Controller {
    private $repo;
    function __construct(WebshopRepositoryInterface $repo) {
        $this->repo = $repo;
    }
}

in the provider flip the binding:

<?php namespace App\Providers;

use App\Repositories\WebshopRepository;
use App\Repositories\WebshopRepositoryInterface;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->bind(WebshopRepositoryInterface::class, WebshopRepository::class);
    }
}
2 likes
bobbybouwmann's avatar

I already notice what's going wrong! The bind method first needs the interface and then the implementation, so updating it to this would do the trick!

$this->app->bind(WebshopRepositoryInterface::class, WebshopRepository::class);

I always call my interface something like this UserRepository and then my implementation the name for what it is implemented for, so in my case EloquentUserRepository ;)

RobertBaelde's avatar

I noticed that, and tried it already. But it doesn't resolve the issue :(

khalidity's avatar

Hi there, I still don't get it the need to use the service provider, instead of using the repo interface/contracts as a type hint at the controller constructor I'm using the repo model itself as a type hint and its working

For example, this is my repository interface,

<?php namespace App\Repositories\Contracts;
interface RepositoryInterface {
    public function all();
}

And this is the repo model,

<?php namespace App\Repositories;
use App\Repositories\Contracts\RepositoryInterface as RepositoryInterface;

Class UserRepository implements RepositoryInterface {
    
    protected $collection;

    public function __construct(){
        $this->collection = 'users';
     }

    public function all(){
        return \DB::collection($this->collection)->get();
    }
}

And the controller itself,

<?php namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;

class UserController extends Controller
{
    private $repo;

    public function __construct(UserRepository $repo) {
        $this->repo = $repo;
    }

    public function all(){
        echo get_class($this->repo);
        $all = $this->repo->all();
        var_dump($all);
        exit;
    }
}
bobbybouwmann's avatar

@khalidity You don't use the repository pattern correctly. Let's say I have on interface with different methods and I have an implementation for Eloquent and an implementation for MongoDb. I would have one interface and I would tell my application to use that interface like this, but how does Laravel know which implementation to use?

public function __construct(UserRepository $repository)
{
    $this->repository = $repository;
}

And your interface can look like this

interface UserRepository {

    public function all();

    public function find($id);

}

We know that we have an Eloquent implementation and a MongoDb implementation and they both need the same methods so our controller is not depending on one of them

class EloquentUserRepository implements UserRepository {

    public function all()
    {
        return User::all();
    }

    public function find($id)
    {   
        return User::findOrFail($id);
    }

}

And at last our mongo implementation

class MongoUserRepository implements UserRepository {

    public function all()
    {
        // all implementation
    }

    public function find($id)
    {   
        // find implementation
    }

}

I hope you see now that Laravel can't know which implementation you want to use. That's where the service providers comes in the play. We tell laravel to bind the interface to a certain implementation. This means that if we tell laravel to work with the Eloquent version laravel will auto create that class instead of the interface

I hope this makes sence to you

khalidity's avatar

@bobbybouwmann hmm.. I'm still a little bit confuse, plz enlight me. I acknowledged that when using the recovery pattern we need an interface to bound/contract the related repository so they will have the same method and function despite of different db connection. Looking at your example above, UserRepository will have two descendants MongoUserRepository and EloquentUserRepository, it means that I need to bind the interface with these two descendants right? correct me if I'm wrong

...
public function register()
    {
        $this->app->bind(RepositoryInterface::class, MongoUserRepository::class);
         $this->app->bind(RepositoryInterface::class, EloquentUserRepository::class);
         
    }
...

There's things that I still can't figure out, if you look at the code below, I will not know which repository is going to be auto create?

<?php namespace App\Http\Controllers;
use App\Repositories\UserRepository;

class UserController extends Controller {
    private $repo;
    function __construct(UserRepository $repo) {
        $this->repo = $repo;
    }
}

If I did something like this below, I will know which repository I'm using on this controller, and still have the same method and function because of contract with UserRepository interface.

<?php namespace App\Http\Controllers;
use App\Repositories\MongoUserRepository;

class UserController extends Controller {
    private $repo;
    function __construct(MongoUserRepository $repo) {
        $this->repo = $repo;
    }
}

If two repos implement the same interface and then auto create the repo based on interface, how can I make a switch for a repo that I need to use for other controller? Or else maybe I'm still missing the point of using the repository pattern?

pmall's avatar

UserRepository will have two descendants MongoUserRepository and EloquentUserRepository, it means that I need to bind the interface with these two descendants right?

No. Obviously your app either use eloquent or mongo.

Also keep in mind dependency injection and interface binding are two different things. You can inject a bare class. Interface binding is a way to easily switch implementation (example here eloquent / mongo).

Please or to participate in this conversation.