anoop Singh
anoop Singh

Reputation: 91

Where do we have to write queries in Laravel: in model, controller or routes?

I'm little confused with the database queries in the laravel, where do we have to write our queries: in controllers, models or routes ?

I've been through many tutorials and I see so much difference. Just creating confusion.

Kindly explain somebody

Upvotes: 7

Views: 12308

Answers (2)

StealthTrails
StealthTrails

Reputation: 2415

Updated Answer

Models in Laravel: Models are used for mapping database tables to classes and defining relationships. Avoid placing complex query logic directly in models.

Querying in Controllers: Handle queries in controller methods rather than route closures. This keeps your routes file clean and aligns with MVC principles.

Service Classes: Encapsulate complex business logic in service classes. This keeps controllers focused on HTTP requests and responses, improving code organization.

Repository Pattern: Abstract data access logic using repositories. Define interfaces and implementations to manage data retrieval and persistence separately from business logic.

Combining Both Patterns:

Controllers: Handle HTTP requests and delegate complex logic to service classes.

Service Classes: Contain business logic and interact with repositories.

Repositories: Manage data access and abstraction. Using these practices helps maintain a clean, scalable, and organized codebase.

Old Answer

You do not write any query in Model. Model is just for mapping the class that you are going to use for a table like User Model will be mapped to users (plural of model name).

You do not write queries in the routes closures like this

Route::get('/', ['as' => 'home', function(){
    $totalProblems = Problem::count();

    $solvedProblems = Problem::where('solved', 1)->get()->count();

    $unsolvedProblems = Problem::where('solved', 0)->get()->count();

    return view('Pages.index', ['totalProblems' => $totalProblems, 'solvedProblems' => $solvedProblems, 'unsolvedProblems' => $unsolvedProblems]);
}]);

This is considered as bad practice, its just for testing purposes.

You always write your queries in the controller method associated with your route like this

Route::get('test', 'HomeController@test');

and in your HomeController

<?php namespace App\Http\Controllers;
use App\Problem;

    class HomeController extends Controller {
    
        public function test(){
            $user = User::all();
            return view('Pages.test')->withUser($user); //or
    
            return view('Pages.test')->with('user' , $user);
        }
    }

Upvotes: 0

Moppo
Moppo

Reputation: 19285

It depends on different factors, but in short you can write them both in Model, Controllers or Repositories

If you're writing a controller action and you need a query that you'll use only once, it's perfectly fine to write the query directly in the controller (or even in the route's closure ).

For example, if you want to get all users of type admin:

$admins = User::where('type', 'admin')->get();

Now, suppose you need to get the admins in more than one controller method; instead of rewriting the same query, you can create a Repository class to wrap the access to the users' Model and write the query inside the Repository:

class UserRepository
{
    public function getAllAdmins()
    {
        return User::where('type', 'admin')->get();
    }
}

Now in your controllers you can inject the Repository and use the same method of the Repository to get the admin users: this will keep your code DRY as you don't have to repeat the same query among the controllers' actions

Controller

public function __construct(UserRepository $userRepo)
{
     $this->userRepo = $userRepo;
} 

//controller action
public function index()
{
     $admins = $this->userRepo->getAllAdmins(); 
}

Finally, let's suppose you need a query to count the number of the admin users. You could write this query in the UserRepository:

public function getAdminNum()
{
    return User::where('type', 'admin')->count();    
}

And it would be ok, but we can note that the User::where('type', 'admin') fragment of the query is shared with the query in getAllAdmins So we can improve this by using query scopes :

User Model

public function scopeAdmins($query)
{
    return $query->where('type', 'admin');    
}

by this, in the UserRepository methods we can rewrite our previous queries as:

public function getAllAdmins()
{
    return User::admins()->get();
} 

public function getAdminNum()
{
    return User::admins()->count();  
}

And i've just showed you a case in which a query would be writed inside a Model

Upvotes: 15

Related Questions