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

Kudos's avatar

Where to place the queries?

Hi there,

I'm having a hard time figuring out where to place the queries, should they just be in the controller method for the particular view? I think that could lead to some serious clusterfuck.

0 likes
27 replies
andy's avatar

Normally I'd say a lot of people follow the following practice:

If your project is rather "large" you would probably use repositories. If that extra layer is a PITA or the project is rather small, then just put everything into models. (I like to create a separate folder for models rather than just them lay all over the place.)

My typical setup: I use my controllers to "control" my models for managing "model stuff" (ie, whatever extends a model like: presenters, translators, and such) and repositories for the actual queries ( I skip the repository interface since that is the layer I find to be a PITA).

Kudos's avatar

Thanks for your explanation, can I get you to post an example? Preferably with use of repositories. If I understand you well, you have your methods in your models to do the work, and you work with them in the controller? I'm not quite sure what a repository means, in this context, maybe you can provide me with a link or such?

I found this link about architecture, maybe that's what you're trying to say? http://laravel.io/forum/06-17-2014-controller-service-repository-architecture However I'm struggling understanding and implementing it.

martinbean's avatar

@Kudos You should never have queries in your controller. Queries belong in models, and even then they should be built up with the query builder as opposed to raw SQL statements.

jlrdw's avatar

@martinbean the controller is where queries go.
Example directly from the documentation:

<?php

namespace App\Http\Controllers;

use DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show a list of all of the application's users.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::table('users')->get();  //THIS IS A QUERY

        return view('user.index', ['users' => $users]);
    }
}
Ori's avatar

@jlrdw Not everything in documentation is a best practice(this is mainly for a simplicity of demonstration). In a case of small web application with only one maintainer it is ok to put queries in controller. But if you work as a team or your project is bigger than usual, you need more abstraction. That is what repositories are for.

martinbean's avatar

@jlrdw The documentation is for example only. There are plenty of things in the documentation that are for demonstrative purposes only and not actually intended to be used in production code. Queries in a controller method is one of those things.

1 like
Ori's avatar

@jlrdw Laracast is also a demonstration( of some features or techniques or technologies), and many times it is being said in video that is just a demonstration and it should be understood literally. Take a look at what MVC and also do not take demonstration videos literally.

anyway we are actually trying to help him, and you are bringing unnecessary confusion and offtopic to this thread

@Kudos take a look at that article I posted earlier, there is also a brief explanation of what repository is and what is it for.

jlrdw's avatar

A model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Photo extends Model
{
    /**
     * Get all of the owning imageable models.
     */
    public function imageable()
    {
        return $this->morphTo();
    }
}

class Staff extends Model
{
    /**
     * Get all of the staff member's photos.
     */
    public function photos()
    {
        return $this->morphMany('App\Photo', 'imageable');
    }
}

class Product extends Model
{
    /**
     * Get all of the product's photos.
     */
    public function photos()
    {
        return $this->morphMany('App\Photo', 'imageable');
    }
}

Retrieving Polymorphic Relations

Once your database table and models are defined, you may access the relationships via your models. For example, to access all of the photos for a staff member, we can simply use the photos dynamic property:

This would go in the controller

$staff = App\Staff::find(1);  //THIS IS THE QUERY GETTING RESULTS FROM MODEL  
                                            // THIS DOES NOT AND SHOULD NEVER BE IN THE MODEL

This would go in the view

foreach ($staff->photos as $photo) {
    //the loop here
}

PERIOD
If you don't understand this, I sincerely hope you aren't writing real world production sites.

1 like
Kudos's avatar

@jlrdw So even though a view uses multiple queries to get data to pass to the view, every single query should be in the respective function in the controller? If I need to find something complex, let's say I have to find a userID first, then use the userID to locale some data in another table, and then use the data located in there to find something else in another table.

Ori's avatar

That is a query ? Is it really ? It is calling a Repository that instantiate a model and perform calls on that model.

To put things straight. I am not saying it is bad calling model(with scopes) from a controller, it is OK and in most cases using repositories is unnecessary overkill, but building a query with querybuilder in a controller is not a good idea for many reasons, such as maintenance or breaking MVC pattern.

so @jlrdw please posting here a code with bad commentary, when you do not know what is it about

andy's avatar

@Kudos

I picked up a lot from this: https://github.com/mrakodol/Laravel-5-Bootstrap-3-Starter-Site

I don't think it has repositories but they are basically just like calling a model: $this->model versus $this->model_repository You will need to call your model within the repository.

I also learned a lot from this: https://github.com/sdebacker/TypiCMS

It has interfaces and scopes and all kinds of goodies to learn about but at the same time more advanced in some ways.

@ documentation and laracast examples.

lol, at least the docs don't put all the example code into the routes file ;)

After watching a lot of Jeffery's videocasts, it "seems" (I could be wrong) he has gone from being very strict about moving things into the proper places to being more pragmatic and suggesting to still follow proper usage but with the idea that sometimes breaking a "rule" makes more sense.

So, why not just make sure that your code is easy to follow, clean as possible, DRY as possible, and have comments that add to understanding rather than just explain what your code already does!

Besides, who knows what flavor of the week design patter is going to make this week's obsolete and old school ;)

Prullenbak's avatar

https://laracasts.com/discuss/channels/laravel/where-to-place-the-queries/replies/107044

This. That's 100% true. You don't put your queries in your models. Queries are returning models.

The only thing you could add is a repository layer. You would add the query

App\Staff::find(1);

to the repository and call something like $this->staffRepository->get(1) in the controller. But a repository is by no means the only way to go. I actually don't like them that much. Not even in bigger projects. That's because I feel like I'm repeating a lot of eloquent stuff in the repositories. But at the end of the day, this all depends on project scope, size and personal/team-preference.

nullReference's avatar

...so after sitting here and reading all of this, it sounds like the quickest, simplest, cleanest thing to do when you need to create a complex custom query with the query builder is to create a private method in your controller class, pass it some parameters, run the query, and return the output to the controller method that's responding to the request...

Yes, I understand this isn't a pattern you would want to utilize for a large scale production application, but for something that just needs to output a couple of custom reports...I'm not seeing the need to adopt an entire repository pattern just to do so.

Please correct me if I am mistaken.

V9द's avatar

Today someone told me don't write queries to controller instead of this write in model. So got this whole conversation, but did not get any strong reason not to write queries in controller. So, looking for some more thoughts.

automica's avatar

The answer is - it depends.

if you have simple queries, you can write them in the controller. Really your controller should be executing Model methods and then passing data the view. If you have complex functionality, its clearer to pass this into Models and then you can write accompanying unit tests to ensure these methods stay working.

1 like
jlrdw's avatar

This being a very old post, I switched to query scopes. A simple find one record I still put in controller, but for a larger query I make a scope:

    public function scopegetPets($query, $petsearch = '')
    {
        $petsearch = $petsearch . "%";
        $query->where('petname', 'like', $petsearch);
        if (ChkAuth::chkRole('admin') === false) { // custom rbac
            $userid = Auth::user()->id;
            $query->where('ownerid', '=', $userid);
        }
        $results = $query->orderBy('petname', 'asc')->paginate(5);
        return $results;
    }

Called from controller like:

$pets = Pet::getPets($petsearch);

Preference has a lot to do with it, but scopes is one way to go.

1 like
Snapey's avatar

preferably with scope names that reflect what they do.

3 likes
rawilk's avatar

Also preferably query scopes that do just one thing. It's not normal to put the entire query into a query scope. And more importantly, it's definitely not normal to finish the query with paginate or get or first in a query scope.

2 likes
ramniksingh's avatar

After reading all this, it is still a mystery.

I personally feel as laravel is really advanced mysterious framework which keeps code so clean that understanding it becomes hard, these discussions are also like that. Really confusing.

1 like
jlrdw's avatar

@ramniksingh Having

$pets = Pet::getPets($petsearch);
   in controller

Then having

->paginate(5);
   in model

is exact same as if in controller I used it like:

$pets = Pet::getPets($petsearch)->paginate(5);

And not used paginate in scope. It's exactly the same.

I am using a dynamic scope with parameter:

Reference:

https://laravel.com/docs/8.x/eloquent#dynamic-scopes

Everything isn't documented, it's a php framework. You can even use regular pdo in a scope.

At runtime eloquent converts to regular pdo / sql.

Tray2's avatar

@ramniksingh Watch some of the free tutorials, specially this one https://laracasts.com/series/laravel-6-from-scratch

As to where to place the queries just follow the KISS rule. Start by placing them in your controllers and if the starts to feel icky move them to your model. In most cases they can stay in the controller.

Some people like to use this or that pattern but unless some company standard or your own preference requires the use of a pattern just follow the KISS rule.

1 like
jlrdw's avatar

@tray2 @ramniksingh Yes, someone else likes the KISS rule. I was a contributor to another framework and the moto was KISS. The old Simple php mvc framework. Been some time now.

But like @tray2 suggested, those videos are good, also code is free on Github to study.

Good luck in your learning.

ramniksingh's avatar

@tray2 @jlrdw Thanks for your suggestions.

I have gone through laravel from scratch and quite comfortable in developing small web application. And keeping queries in controllers are okay in my opinion when application is small.

Things gets confusing when thinking about a large application like a basic ERP. In complex and many queries, what would be the place to keep queries, specially the database queries which are common to many controllers.

Tray2's avatar

If the query is common between many controllers I probably use this https://laravel.com/docs/8.x/views#sharing-data-with-all-views

If you have your queries in the model or in the controller is up to you. The most imortant thing is that you are consistant.

If we are talking an ERP system you probably don't just one table per controller but rather multiple ones. Then for index and show methods consider using database views to keep down the complexity of the queries in your model or controller.

Please or to participate in this conversation.