Understanding Laravel Query Scopes: Benefits and an eCommerce Example

In the world of Laravel, query scopes are powerful tools that help developers write cleaner, more manageable, and reusable code. If you’re working on an eCommerce project or any other type of application, query scopes can significantly enhance the maintainability and readability of your codebase. In this blog post, we’ll explore what query scopes are, their benefits, and how to use them with an example from an eCommerce application.


What are Laravel Query Scopes?

Query scopes in Laravel are custom methods defined within a model that allow you to encapsulate reusable query logic. By defining a query scope, you can apply common constraints or filters to your database queries in a clean and concise manner.


Benefits of Using Query Scopes

  1. Reusability:
    Query scopes enable you to define a query once and reuse it throughout your application. This means less code duplication and a more consistent application of query logic.
  2. Readability:
    By abstracting complex query logic into named methods, your queries become more readable and self-explanatory. This makes your code easier to understand and maintain, especially for new team members or contributors.
  3. Maintainability:
    When you need to update the query logic, you only have to make changes in one place. This centralization of query logic makes your codebase easier to maintain and reduces the risk of introducing bugs.

Example: Using Query Scopes in an eCommerce Application

Let’s consider an eCommerce application where we need to filter products based on their status and price range. We can achieve this efficiently using query scopes.

Defining Query Scopes:

First, we define our query scopes in the Product model.

// Product.php model file
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    // Local scope for active products
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    // Local scope for products within a price range
    public function scopePriceBetween($query, $minPrice, $maxPrice)
    {
        return $query->whereBetween('price', [$minPrice, $maxPrice]);
    }

    // Local scope for new arrivals
    public function scopeNewArrivals($query)
    {
        return $query->where('created_at', '>=', now()->subWeek());
    }
}

In the above example, we defined three query scopes: active, priceBetween, and newArrivals. The active scope filters products that have an ‘active’ status, the priceBetween scope filters products within a specified price range, and the newArrivals scope filters products added within the last week.

Using Query Scopes:

Now, let’s see how to use these query scopes in our application.

// In a controller or any part of your application
use App\Models\Product;

$activeProducts = Product::active()->get();
$affordableProducts = Product::priceBetween(100, 500)->get();
$newArrivals = Product::newArrivals()->get();

With just a couple of lines, we can apply our query scopes to filter products. The active() scope retrieves all active products, the priceBetween(100, 500) scope retrieves products priced between $100 and $500, and the newArrivals() scope retrieves products added in the last week.


Enhancing Maintainability and Reusability

Imagine you need to update the logic for new arrivals to check for products added in the last two weeks instead of one. Without query scopes, you would need to find and update each occurrence of this query in your codebase. However, with query scopes, you only need to update the scope method in the Product model:

// Updated new arrivals scope in Product model
public function scopeNewArrivals($query)
{
    return $query->where('created_at', '>=', now()->subWeeks(2));
}

This single change updates the query logic wherever the newArrivals() scope is used, ensuring consistency and reducing the risk of errors.


More Examples of Query Scopes

To further illustrate the power and versatility of query scopes, here are more examples that can be used in various contexts:

  1. Scope for Discounted Products:
public function scopeDiscounted($query)
{
    return $query->where('discount', '>', 0);
}

Usage:

$discountedProducts = Product::discounted()->get();
  1. Scope for Products in a Specific Category:
public function scopeInCategory($query, $categoryId)
{
    return $query->where('category_id', $categoryId);
}

Usage:

$electronics = Product::inCategory(1)->get();
  1. Scope for Out of Stock Products:
public function scopeOutOfStock($query)
{
    return $query->where('stock', 0);
}

Usage:

$outOfStockProducts = Product::outOfStock()->get();
  1. Scope for Products with High Ratings:
public function scopeHighlyRated($query)
{
    return $query->where('rating', '>=', 4);
}

Usage:

$highlyRatedProducts = Product::highlyRated()->get();

Conclusion

Query scopes are a powerful feature in Laravel that promote code reusability, readability, and maintainability. By encapsulating query logic within models, you can simplify your code and make it more manageable. In an eCommerce application, query scopes can be particularly useful for filtering products based on various criteria, ensuring that your queries remain clean and efficient.

If you found this post helpful, be sure to subscribe to our blog for more Laravel tips and tutorials. Happy coding!