andersao / l5-repository

Laravel 5 - Repositories to abstract the database layer
http://andersao.github.io/l5-repository
MIT License
4.19k stars 878 forks source link

Best Practice using repository #505

Open jaysongyn opened 6 years ago

jaysongyn commented 6 years ago

I would like to know the best way to approach this query:

First approach - Creating query in User service:

public function getUsersByRole($role)
{
    return $this->repository
        ->with(['role'])->whereHas('role', function ($query) {
            $query->where('name', 'admin');
        })
        ->paginate();
}

Second aproach, creating criteria: Criteria:

public function apply($model, RepositoryInterface $repository)
{
    $model = $model->whereHas('role', function ($query) {
        $query->where('name', 'admin');
    });
    return $model;
}

UserService:

public function getUsersByRoles($role)
{
    return $this->repository->with('role')
        ->pushCriteria(new UserByRoleCriteria())
        ->paginate(request('limit'));
}

Third Using method in UserRepository UserRepository:

public function getUserByRole($role)
{
    return $this->with(['role'])->whereHas('role', function ($query) {
        $query->where('name', 'admin');
    })->paginate();
}

UserService:

public function getUsersByRole($role)
{
    return $this->repository->getUserByRole($role);
}

When should I create criteria or creating method on UserRepository or create query in my service?

ricardofilho6 commented 6 years ago

I have the same doubt as yours

HerreraG commented 6 years ago

Hello, if we look at the documentation

Criteria are a way to change the repository of the query by applying specific conditions according to your needs.

Criteria Queries

so watching this I'll use this approach

Criteria:

public function apply($model, RepositoryInterface $repository)
{
    $model = $model->whereHas('role', function ($query) {
        $query->where('name', 'admin');
    });
    return $model;
}

UserRepository:

public function getUserByRole($role)
{
    return $this->with('role')
        ->pushCriteria(new UserByRoleCriteria())
        ->paginate(request('limit'));
}

UserService:

public function getUsersByRole($role)
{
    return $this->repository->getUserByRole($role);
}

I would not use criterial for this query since it can be solved with the base methods that the repository gives us.

Because it would be a lot of design for a simple query.

Excuse my english

johannesschobel commented 6 years ago

Hey @jaysongyn ,

as @HerreraG describes, i would also go for the Criteria approach, because it is quite re-usable.. Imagine, that you may need to apply the same where-condition over and over again (e.g., you may want to only output Products that are is_active flagged in your database). So you may easily do this within one Criteria and apply it constantly to your Repository Requests.

Further, it contributes to a better maintainability of your application - because the entire "logic" on how to select respective Products that are active is within this Criteria..

Hope this helps

gustavomedeiross commented 4 years ago

I would go for the Criteria inside the repository itself. If you think about it from a DDD/SOLID approach, it makes more sense, because the service doesnt need to know how the data is going to be returned, it just needs to know what is going to be returned.

This way we can separate the responsibilities better.

Any other opinions?