2

I am currently creating an API using lumen and I'm not entirely confident about where I should be putting my database queries. I am using the Repository pattern and currently my layout is like so:

  1. Controller loads Custom Repository
  2. Repository method contains eloquent query and returns result.

Controller --> Custom Repository --> Model

Controller <-- Custom Repository <-- Model

-- A high level code example of how I am currently doing it:

Controller.php

public function browse()
{
    // customRepo added via dependency injection
    $this->customRepo->browse()
}

customRepo.php

public function browse()
{
    // other logic here
    return Member::where('active', 1)->orderBy('date', 'desc')->get()
}

I am using Eloquent to make queries to the database and am currently all of these calls are happening inside the Repository which feels a bit odd to me because my Repositories are filling up with Eloquent (and some query builder) queries however I have seen from a few sources that it's not correct to put the queries inside the model.

I feel like my current approach is probably correct I just wanted to see if anyone could definitively tell me which is best - it doesn't make a whole lot of sense for me to pad out the models with custom methods if not needed.

Countach
  • 597
  • 1
  • 10
  • 20

2 Answers2

4

A few points to consider. First, some clarifications on terminology. The Repository pattern you've exemplified is not actually a Repository pattern. It's more akin to a Data Access Object pattern. See quentin-starin's answer for a concise description of the differences between the two. Second, a model in MVC architecture is more than simply a class which extends (in this case Eloquent's) Model class. A lot's been written about it but for brevity's sake, the model is generally a composite aspect of an MVC application which deals with managing data in addition to the domain/business logic. I will use the term entity to refer to the specific Eloquent-based classes you've created (e.g. - Member). Given this understanding, (for code-reuse/loose-coupling/SRP/etc.), it can certainly be beneficial to place any queries within the model. But it is a good idea not to deal with data persistence directly in your entities. The remaining question being, "How should I access the model and/or entities?".

One method I have seen and used is to call a repository/DAO's methods directly from the controller as you are doing. For the sake of testability this will frequently be accomplished by injecting an instance of the entity in question to the repository class. For example, within your customRepo.php file you could create something similar to the following:

protected $model;

public function __construct(\App\Member $model)
{
    $this->model = $model;
}

public function getActiveMembers()
{
    return $this->model->where('active', 1)->orderBy('date', 'desc')->get()
}

Another approach is to create an additional layer of abstraction between the controller and repository via a service layer where the calls to the repository/etc. will reside. This service layer can be a place to fire domain events, wrap multiple data access methods in database transactions, etc. My personal approach is to create new layers of abstraction when I recognize a need for them and/or start to violate SOLID principles. Until then, KISS.

Community
  • 1
  • 1
alaric
  • 987
  • 5
  • 10
0

Putting your queries in the repository, like you are doing, is correct, in my opinion, and not in violation of the idea that you shouldn't put queries in the model. In other words, I feel you're mixing the concepts of repositories and models.

A repository is a bag of stuff of a particular type, and knows how to store and retrieve items from this bag.

A model contains little or no functionality other than business logic to deal with properties of a model correctly (calculated of attributes come to mind).

Erwin Wessels
  • 2,972
  • 1
  • 24
  • 17