Don't just create the Model, implement Repository Pattern


Mar 16, 2018    Janaki Mahapatra, Laravel

Think a scenario where your application uses MySQl database, and you need to switch to a different DB,that means are you going to rewrite your database logic again?. Thanks to Laravel Repository Pattern, which does that for you. Since the Repository Pattern uses interfaces as contracts, your application logic will remain the same and all you have to do is change out the repository. Sounds easy, right? Let’s dive in with a simple example. Lets create a model with a migration file
php artisan make:model Sample -m
Let say we have few columns id, name and email
public function up()
    {
        Schema::create('samples', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();         
            $table->timestamps();
        });
    }
and run the migration as php artisan migrate and our table is ready. Now Lets create two folders under app directory 1. Repositories 2. ServiceProvider Create the Repository Interface
namespace App\Repositories;

interface MySampleInterface
{
    public function getAll();
    
    public function getById($id);
}
Create the Repository Class
namespace App\Repositories;
use App\Sample;
class MySample implements MySampleInterface
{

    public function getAll()
    {
        return Sample::all();
    }

    public function getById($id)
    {
        return Sample::find($id);
    }
}
Register our Repository with Laravel’s IoC Container Create a new MySampleServiceProvider class which will extends the ServiceProvider
namespace App\ServiceProvider;

use Illuminate\Support\ServiceProvider;

class MySampleServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('App\Repositories\MySampleInterface','App\Repositories\MySample');
    }
}
The last step is to add our custom provider in config/app.php as App\ServiceProvider\MySampleServiceProvider::class, Now it is ready to serve in our Controller. Let say we have a controller SampleController
namespace App\Http\Controllers;

use App\Repository\MySampleInterface;
use Illuminate\Http\Request;

class SampleController extends Controller
{
    protected $customObj;

    public function __construct(MySampleInterface $interface)
    {
        $this->customObj = $interface;
    }

    public function test(){
        return $this->customObj->getAll();
    }
}
in route.php add a route Route::get('/test','SampleController@test'); and browse http://yourUrl/test.You can see the result. Let say if you want to switch to a different database, then just create another Repository Class, update the class in IOC container and you are good to go. So here you go
namespace App\Repositories;
use Illuminate\Support\Collection;
class MySample2 implements MySampleInterface
{

    public function getAll()
    {
        return  new Collection([1,2,3,4,5]);
    }

    public function getById($id)
    {
        return  new Collection([1]);
    }
}
and Update the ServiceProvider class
namespace App\ServiceProvider;

use Illuminate\Support\ServiceProvider;

class MySampleServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('App\Repositories\MySampleInterface','App\Repositories\MySample2');
    }
}