user991
user991

Reputation: 1369

Laravel 4: How to correctly work with Models in Repositories

Read books From Apprentice To Artisan and Implementing Laravel by Chris Fidao and now i don't know how to correctly work with Models in Repositories.

In Implementing laravel book author is working with models in this way:

Example #1

<?php
use MyApp\Interfaces\UserInterface;
use Illuminate\Database\Eloquent\Model;

class UserRepository implements UserInterface
{
    protected $user;

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

    public function find($userId)
    {
        return $this->user->find($userId);
    }
}

But that can by done in other way, not injecting Model as a dependency, like this:

Example #2 Built example using tutorial http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories/

<?php
use MyApp\Interfaces\UserInterface;
use MyApp\Models\User\User;

class UserRepository implements UserInterface
{
    public function find($userId)
    {
        return User::with('profile')->find($userId);
    }
}

Why in first example Model is injected, why not use directly Model like in example two?

Which way is correct and why ?

Also which way will be more testable with integrated to laravel UnitTest package ?

Upvotes: 0

Views: 2780

Answers (2)

MTVS
MTVS

Reputation: 2096

I think if a Repository is intended to be the Eloquent implementation of a RepositoryInterface it isn't a bad idea to use the EloquentModel directly.

Upvotes: 0

Antonio Carlos Ribeiro
Antonio Carlos Ribeiro

Reputation: 87719

The example 2 is bad because it's coupling your repository to a particular implementation of the User model.

Every time you use your repository it'll need to instantiate Univemba\Models\User\User. The whole idea of Dependency Injection is to inject (send) in to your object whatever dependencies it has. If your object needs a Model to work with you can send it a Laravel Eloquent Model, but any of your co-workers could also need to send to it a Doctrine Model. But if you couple your class to Eloquent, this isn't possible.

So in the first example, there is no instantiation happening on your code and it's not using a concrete class directly as in the second:

return User::with('profile')->find($userId);

It is receiving an implementation in the process of its instantiation:

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

There are better ways to do that, because it is still expecting a concrete class while it should be expecting an implementation of an interface

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

In this case you just need to pass to your object something that implements ModelInterface, which could be

Univemba\Models\EloquentModel

Or

Univemba\Models\DoctrineModel

Because both would be implementing

Univemba\Models\ModelInterface

Upvotes: 2

Related Questions