How to Use Laravel 10 Scope to Streamline Database Queries?

20-Dec-2023

.

Admin

How to Use Laravel 10 Scope to Streamline Database Queries?

Hello Dev,

Today, how to use Laravel 10 scope to streamline database queries is our main topic. it's a simple example of how to use query scope in Laravel 10. This article will give you a simple example of Laravel to automatically handle a cast in a query. we will help you to give an example of how to streamline a query - data management. Here, Creating a basic example of how can queries streamline data analysis and visualization.

Laravel Scopes in Eloquent ORM empower developers to craft efficient, reusable query constraints. This guide explores Laravel Scopes, demonstrating their effective implementation in web applications.

Step 1: Implementing Local Scopes in Laravel Eloquent


Local scopes in Laravel enable you to encapsulate common query logic directly within your Eloquent models. By creating local scopes, you can effortlessly apply specific constraints to your database queries, enhancing the readability and maintainability of your code.

Example:

Scope by Status:Implement a local scope to retrieve only active users from the database based on their status.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'name',

'email',

'password',

'status',

];

/**

* The attributes that should be hidden for serialization.

*

* @var array<int, string≶

*/

protected $hidden = [

'password',

'remember_token',

];

/**

* The attributes that should be cast.

*

* @var array<string, string≶

*/

protected $casts = [

'email_verified_at' => 'datetime',

'password' => 'hashed',

];

/**

* Get the Active Scope

*

* @return string

*/

public function scopeActive($query)

{

return $query->where('status', 'active');

}

}

We can use the scope like the below code.

$activeUsers = User::active()->get();

Scope by Category: Create a scope to fetch products belonging to a specific category.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Car extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'car_name',

'car_price',

'car_model',

];

/**

* Get the Price Scope

*

* @return string

*/

public function scopeByPrice($query, $price)

{

return $query->where('car_price', $price);

}

}

We can use the scope like the below code.

$car = Car::byprice(10,00,000)->get();

Scope with Parameters: Develop a scope to filter results based on user-defined criteria like date ranges.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Car extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'car_name',

'car_price',

'car_model',

'release_date',

];

/**

* Get the ReleaseBetween Scope

*

* @return string

*/

public function scopeReleaseBetween($query, $startDate, $endDate)

{

return $query->whereBetween('release_date', [$startDate, $endDate]);

}

}

We can use the scope like the below code.

$releaseBetweenDates = Car::releaseBetween('2023-01-01', '2023-07-31')->get();

Step 2: Working with Global Scopes in Laravel

Global scopes are automatically applied to all queries on a specific Eloquent model. They serve as excellent tools for defining universal restrictions and ensuring consistency throughout your application.

Example:

Global Scope for Multi-Tenancy: Set up a global scope to retrieve data specific to a particular tenant within a multi-tenant application.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Product extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'product_name',

'order_id',

'product_price',

'product_quantity',

];

/**

* Get the addGlobalScope

*

* @return string

*/

protected static function booted()

{

static::addGlobalScope('product', function (Builder $builder) {

$builder->where('order_id', auth()->user()->order_id);

});

}

}

We can use the scope like the below code.

$product = Product::all();

Soft Deleting with Global Scope: Implement a global scope to automatically filter out soft-deleted records from all queries.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Product extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'product_name',

'product_price',

'product_quantity',

];

/**

* Get the addGlobalScope

*

* @return string

*/

protected static function booted()

{

static::addGlobalScope('soft_delete', function (Builder $builder) {

$builder->whereNull('deleted_at');

});

}

}

We can use the scope like the below code.

$product = Product::all();

Step 3: Dynamic Scopes in Laravel

Dynamic scopes provide the ability to create versatile query constraints that can accept parameters during runtime. This flexibility enhances the adaptability and power of your database queries.

Example:

Filtering Products by Price: Create a dynamic scope that allows users to filter products based on price ranges.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Product extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'product_name',

'product_price',

'product_quantity',

];

/**

* Get the PriceRange Scope

*

* @return string

*/

public function scopePriceRange($query, $minPrice, $maxPrice)

{

return $query->whereBetween('product_price', [$minPrice, $maxPrice]);

}

}

We can use the scope like the below code.

$Products = Product::priceRange(100, 500)->get();

Sorting Records Dynamically: Implement a dynamic scope that enables users to sort records based on different criteria.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Order extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'order_name',

'order_price',

'order_quantity',

];

/**

* Get the SortBy Scope

*

* @return string

*/

public function scopeSortBy($query, $column, $direction = 'asc')

{

return $query->orderBy($column, $direction);

}

}

We can use the scope like the below code.

$sorted = Order::sortBy('created_at', 'desc')->get();

Step 4: Utilizing Laravel Scope for Security

Laravel Scopes plays a pivotal role in enhancing the security of your application. By controlling data access and permissions, you can strengthen your app’s protection against unauthorized access.

Example:

Securing User Profiles: Develop a scope that restricts access to user profiles, allowing only the profile owner or admin to view sensitive information.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'user_id',

'user_name',

'user_email',

'user_password',

];

/**

* The attributes that should be hidden for serialization.

*

* @var array<int, string≶

*/

protected $hidden = [

'password',

'remember_token',

];

/**

* The attributes that should be cast.

*

* @var array<string, string≶

*/

protected $casts = [

'email_verified_at' => 'datetime',

'password' => 'hashed',

];

/**

* Get the AccessibleByUser Scope

*

* @return string

*/

public function scopeAccessibleByUser($query, $userId)

{

return $query->where(function ($query) use ($userId) {

$query->where('user_id', $userId)->orWhere('is_public', true);

});

}

}

We can use the scope like the below code.

$user = User::accessibleByUser(auth()->user()->id)->get();

Manage user permissions and access rights for specific resources by creating a scope.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Resource extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'id',

'name',

'email',

'required_role',

];

/**

* Get the AccessibleByRole Scope

*

* @return string

*/

public function scopeAccessibleByRole($query, $role)

{

return $query->where('required_role', $role);

}

}

We can use the scope like the below code.

$accessibleResources = Resource::accessibleByRole('admin')->get();

Step 5: Best Practices for Laravel Scope Usage

To leverage Laravel Scopes effectively, it's crucial to adhere to best practices that guarantee maintainable and efficient code.

Example:

Highlight the advantages of reusable scopes and demonstrate how they contribute to a cleaner codebase.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Product extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'product_name',

'product_price',

'product_quantity',

'published',

'featured',

];

/**

* Get the Published Scope

*

* @return string

*/

public function scopePublished($query)

{

return $query->where('published', true);

}

/**

* Get the Featured Scope

*

* @return string

*/

public function scopeFeatured($query)

{

return $query->where('featured', true);

}

}

We can use the scope like the below code.

$product = Product::published()->featured()->get();

Avoiding Overly Complex Scopes: Illustrate why it is crucial to maintain simplicity and focus in scopes to prevent potential issues.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

use Laravel\Sanctum\HasApiTokens;

class Order extends Authenticatable

{

use HasApiTokens, HasFactory, Notifiable;

/**

* The attributes that are mass assignable.

*

* @var array<int, string≶

*/

protected $fillable = [

'order_name',

'order_quantity',

'shipped_at',

];

/**

* Get the ShippedWithinDays Scope

*

* @return string

*/

public function scopeShippedWithinDays($query, $days)

{

return $query->whereDate('shipped_at', '>=', now()->subDays($days));

}

}

We can use the scope like the below code.

$order = Order::shippedWithinDays(30)->get();

Testing Scopes: Demonstrate how to write unit tests for scopes to ensure their correctness and prevent regressions.

public function testScopePublished()

{

factory(Post::class)->create(['published' => true]);

factory(Post::class)->create(['published' => false]);

$publishedPosts = Post::published()->get();

$this->assertCount(1, $publishedPosts);

}

I hope it can help you...

#Laravel 10