😇Scope trong Laravel, Removing Global Scopes, Local Scopes, Dynamic Scopes full (ok)

https://viblo.asia/p/scope-trong-laravel-jvElamGAlkw

Cách 1: Viết file riêng

C:\xampp8\htdocs\hanam\app\Scopes\AncientScope.php

<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AncientScope implements Scope
{
  /**
   * Apply the scope to a given Eloquent query builder.
   *
   * @param  \Illuminate\Database\Eloquent\Builder  $builder
   * @param  \Illuminate\Database\Eloquent\Model  $model
   * @return void
   */
  public function apply(Builder $builder, Model $model)
  {
    $builder->where('created_at', '<', now());
  }
}

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  protected static function booted()
  {
    static::addGlobalScope(new AncientScope());
  }
  // protected static function booted()
  // {
  //   static::addGlobalScope('ancient', function (Builder $builder) {
  //     $builder->where('created_at', '<', now());
  //   });
  // }
}

Cách 2: Viết trực tiếp tròn model

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  // protected static function booted()
  // {
  //   static::addGlobalScope(new AncientScope());
  // }
  protected static function booted()
  {
    static::addGlobalScope('ancient', function (Builder $builder) {
      $builder->where('created_at', '<', now());
    });
  }
}

Removing Global Scopes

Trường hợp 1: Rời tất cả crops trong AncientScope

C:\xampp8\htdocs\hanam\app\Scopes\AncientScope.php

<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AncientScope implements Scope
{
  /**
   * Apply the scope to a given Eloquent query builder.
   *
   * @param  \Illuminate\Database\Eloquent\Builder  $builder
   * @param  \Illuminate\Database\Eloquent\Model  $model
   * @return void
   */
  public function apply(Builder $builder, Model $model)
  {
    $builder->where('created_at', '<', now());
  }
}

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  protected static function booted()
  {
    static::addGlobalScope(new AncientScope());
  }
  // protected static function booted()
  // {
  //   static::addGlobalScope('ancient', function (Builder $builder) {
  //     $builder->where('created_at', '<', now());
  //   });
  // }
}

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    // $user = User::query();
    // $users = $user->get();
    // $users = User::all();
    $users = User::withoutGlobalScope(AncientScope::class)->get();
    return view("welcome")->with(compact('users'));
  }
  public function scopeName($query, $request)
  {
    if ($request->has('name')) {
      $query->where('name', 'LIKE', '%' . $request->name . '%');
    }
    return $query;
  }
  public function scopeStatus($query, $request)
  {
    if ($request->has('status')) {
      $query->where('status', $request->status);
    }
    return $query;
  }
  public function scopeBirthday($query, $request)
  {
    if ($request->has('birthday')) {
      $query->whereDate('birthday', $request->birthday);
    }
    return $query;
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

Trường hợp 2: Rời cụ thể crop

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    // $user = User::query();
    // $users = $user->get();
    // $users = User::all();
    // $users = User::withoutGlobalScope(AncientScope::class)->get();
    $users = User::withoutGlobalScope('ancient')->get();
    return view("welcome")->with(compact('users'));
  }
  public function scopeName($query, $request)
  {
    if ($request->has('name')) {
      $query->where('name', 'LIKE', '%' . $request->name . '%');
    }
    return $query;
  }
  public function scopeStatus($query, $request)
  {
    if ($request->has('status')) {
      $query->where('status', $request->status);
    }
    return $query;
  }
  public function scopeBirthday($query, $request)
  {
    if ($request->has('birthday')) {
      $query->whereDate('birthday', $request->birthday);
    }
    return $query;
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  // protected static function booted()
  // {
  //   static::addGlobalScope(new AncientScope());
  // }
  protected static function booted()
  {
    static::addGlobalScope('ancient', function (Builder $builder) {
      $builder->where('created_at', '<', now());
    });
  }
}

Local Scopes

Trường hợp 1: Sử dụng 1 scop

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  // protected static function booted()
  // {
  //   static::addGlobalScope(new AncientScope());
  // }
  // protected static function booted()
  // {
  //   static::addGlobalScope('ancient', function (Builder $builder) {
  //     $builder->where('created_at', '<', now());
  //   });
  // }
  /**
   * Scope a query to only include popular users.
   *
   * @param  \Illuminate\Database\Eloquent\Builder  $query
   * @return \Illuminate\Database\Eloquent\Builder
   */
  public function scopeCreatedAt($query)
  {
    return $query->where('created_at', '>', now());
  }
}

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    // $user = User::query();
    // $users = $user->get();
    // $users = User::all();
    // $users = User::withoutGlobalScope(AncientScope::class)->get();
    // $users = User::withoutGlobalScope('ancient')->get();
    $users = User::createdat()->orderBy('created_at')->get();
    return view("welcome")->with(compact('users'));
  }
  public function scopeName($query, $request)
  {
    if ($request->has('name')) {
      $query->where('name', 'LIKE', '%' . $request->name . '%');
    }
    return $query;
  }
  public function scopeStatus($query, $request)
  {
    if ($request->has('status')) {
      $query->where('status', $request->status);
    }
    return $query;
  }
  public function scopeBirthday($query, $request)
  {
    if ($request->has('birthday')) {
      $query->whereDate('birthday', $request->birthday);
    }
    return $query;
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

Trường hợp 2.1: Sử dụng nhiều scops

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  // protected static function booted()
  // {
  //   static::addGlobalScope(new AncientScope());
  // }
  // protected static function booted()
  // {
  //   static::addGlobalScope('ancient', function (Builder $builder) {
  //     $builder->where('created_at', '<', now());
  //   });
  // }
  /**
   * Scope a query to only include popular users.
   *
   * @param  \Illuminate\Database\Eloquent\Builder  $query
   * @return \Illuminate\Database\Eloquent\Builder
   */
  public function scopeCreatedAt($query)
  {
    return $query->where('created_at', '>', now());
  }
  public function scopeStatus($query, $request)
  {
    if ($request->has('status')) {
      $query->where('status', $request->status);
    }
    return $query;
  }
}

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    // $user = User::query();
    // $users = $user->get();
    // $users = User::all();
    // $users = User::withoutGlobalScope(AncientScope::class)->get();
    // $users = User::withoutGlobalScope('ancient')->get();
    $users = User::createdat()->status($request)->orderBy('created_at')->get();
    return view("welcome")->with(compact('users'));
  }

  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

Trường hợp 2.2 Sử dụng nhiều scops

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  public function scopeName($query, $request)
  {
    if ($request->has('name')) {
      $query->where('name', 'LIKE', '%' . $request->name . '%');
    }
    return $query;
  }
  public function scopeStatus($query, $request)
  {
    if ($request->has('status')) {
      $query->where('status', $request->status);
    }
    return $query;
  }
}

C:\xampp8\htdocs\hanam\resources\views\welcome.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Laravel</title>
</head>
<body class="antialiased">
  <form action="{{ route('index') }}">
    <input type="text" name="name" value="{{ request()->input('name') }}"> <br/>
    <p><label for="name">0</label><input type="radio" name="status" @if(request()->input('status') == 0) checked @endif value="0"><label for="name">1</label><input type="radio" name="status" @if(old('status') == 1) checked @endif value="1"></p>
    <p><input type="type" name="birthday" value="{{ request()->input('birthday') }}"> use: whereDate</p>
    <input type="submit" value="Submit">
  </form>
  @foreach ($users as $key => $user)
  <p>{{ $key + 1 }}👍 Name: {{ $user->name }} Status: {{ $user->status }}  Date: {{ $user->created_at }}</p>
  @endforeach
</body>
</html>

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    $users = User::query()->name($request)->status($request)->get();
    return view("welcome")->with(compact('users'));
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

C:\xampp8\htdocs\hanam\database\migrations\2014_10_12_000000_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('users', function (Blueprint $table) {
      $table->id();
      $table->string('name');
      $table->string('status');
      $table->string('email')->unique();
      $table->timestamp('email_verified_at')->nullable();
      $table->string('password');
      $table->rememberToken();
      $table->timestamps();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('users');
  }
}

C:\xampp8\htdocs\hanam\database\factories\UserFactory.php

<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      'name' => $this->faker->name(),
      'status' => $this->faker->randomElement([0,1]),
      'email' => $this->faker->unique()->safeEmail(),
      'email_verified_at' => now(),
      'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
      'remember_token' => Str::random(10),
    ];
  }
  /**
   * Indicate that the model's email address should be unverified.
   *
   * @return \Illuminate\Database\Eloquent\Factories\Factory
   */
  public function unverified()
  {
    return $this->state(function (array $attributes) {
      return [
        'email_verified_at' => null,
      ];
    });
  }
}

C:\xampp8\htdocs\hanam\database\seeders\DatabaseSeeder.php

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    User::factory(10)->create();
  }
}

Dynamic Scopes

C:\xampp8\htdocs\hanam\app\Models\User.php

<?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;
use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Builder;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'status',
    'email',
    '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',
  ];
  /**
   * The "booted" method of the model.
   *
   * @return void
   */
  // public function scopeName($query, $request)
  // {
  //   if ($request->has('name')) {
  //     $query->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   return $query;
  // }
  // public function scopeStatus($query, $request)
  // {
  //   if ($request->has('status')) {
  //     $query->where('status', $request->status);
  //   }
  //   return $query;
  // }
  /**
   * Scope a query to only include users of a given type.
   *
   * @param  \Illuminate\Database\Eloquent\Builder  $query
   * @param  mixed  $type
   * @return \Illuminate\Database\Eloquent\Builder
   */
  public function scopeOfType($query, $type)
  {
    return $query->where('email', $type);
  }
}

C:\xampp8\htdocs\hanam\app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Scopes\AncientScope;
use Illuminate\Http\Request;
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  // public function index(Request $request)
  // {
  //   $request->flash();
  //   $user = User::query();
  //   if ($request->has('name')) {
  //     $user->where('name', 'LIKE', '%' . $request->name . '%');
  //   }
  //   if ($request->has('status')) {
  //     $user->where('status', $request->status);
  //   }
  //   if ($request->has('birthday')) {
  //     $user->whereDate('created_at', $request->birthday);
  //   }
  //   $users = $user->get();
  //   return view("welcome")->with(compact('users'));
  // }
  public function index(Request $request)
  {
    $users = User::ofType('emard.lavonne@example.org')->get();
    return view("welcome")->with(compact('users'));
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    //
  }
  /**
   * Display the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function show(User $user)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function edit(User $user)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, User $user)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\User  $user
   * @return \Illuminate\Http\Response
   */
  public function destroy(User $user)
  {
    //
  }
}

Scope trong Laravel.

Happy New Year

Chào các bạn, ngày hôm này mình sẽ cùng các bạn tìm hiểu qua cách sử dụng scope cơ bản trong Laravel.

Global Scope

Hãy tưởng tượng rằng bạn cần thêm một ràng buộc vào tất cả các truy vấn tới model. Nếu các bạn đã từng tìm hiểu qua soft delete trong laravel thì nó chính là một dạng global scope, mỗi khi truy vấn tới model sẽ chỉ lấy ra các bản ghi chưa được xóa mềm từ database. Viết một global scope sẽ giúp chúng ta thuận tiện hơn khi thêm ràng buộc tới từng truy vấn tới model.

Writing Global Scopes

Đầu tiên chúng ta tạo một class implement interface Illuminate\Database\Eloquent\Scope . Interface Scope yêu cầu bạn phải có một phương thức apply. Sau đó chúng ta có thể thêm các mệnh đề where hoặc ràng buộc để giống như ví dụ dưới đây:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class AncientScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('created_at', '<', now()->subYears(2000));
    }
}

Applying Global Scopes

Để có thể thực hiện gán một global scope cho một model bạn cần phải ghi đè phương thức static booted của model và gọi phương thức addGlobalScope của model:

<?php

namespace App\Models;

use App\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope(new AncientScope);
    }
}

Sau khi chúng ta đã thêm global scope như ví dụ trên, ghi truy vấn User::all() câu truy vấn bây giờ sẽ tương tự như sau:

select * from `users` where `created_at` < 0021-02-18 00:00:00

Anonymous Global Scopes

Eloquent cũng giúp chúng ta có thể thêm một global scope bằng closures, khi sử dụng closures để định nghĩa global scope bạn nên xác định tên global scope ở tham số đầu tiên như ví dụ dưới đây:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope('ancient', function (Builder $builder) {
            $builder->where('created_at', '<', now()->subYears(2000));
        });
    }
}

Removing Global Scopes

Đương nhiên cũng có nhiều trường hợp chúng ta không cần dùng đến global scope cho một truy vấn nào đó, Laravel đã giúp chúng ta tất cả mọi thử rồi bạn chỉ cần sử dụng phương thức withoutGlobalScope với tham số đầu tiên là tên class scope của bạn hoặc nếu bạn sử dụng closures để định nghĩa global scope bạn cần thêm vào tên của global scope đó:

//class scope
User::withoutGlobalScope(AncientScope::class)->get();

//closures scope
User::withoutGlobalScope('ancient')->get();

Nếu bạn muốn xóa tất cả ràng buộc global scope hoặc một vài cái thì bạn có thể sủ dụng phương thức withoutGlobalScopes

// Remove all of the global scopes...
User::withoutGlobalScopes()->get();

// Remove some of the global scopes...
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

Local Scopes

Khác với global scope là luôn gọi đến ràng buộc mỗi khi truy vấn, local scope sẽ giúp bạn định nghĩa những trường hợp bạn cần thêm ràng buộc và gọi tới nó bất cứ đâu. Để định nghĩa một local scope bạn cần thêm một phương thức bắt đầu với scope trong model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include popular users.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    /**
     * Scope a query to only include active users.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

Utilizing A Local Scope

Để sử dụng local scope cũng đơn giản thôi chúng ta chỉ cần gọi tới tên scope mỗi khi muốn truy vấn tới model ví dụ:

use App\Models\User;

$users = User::popular()->active()->orderBy('created_at')->get();

Và bạn để ý rằng không có chứ scope phía trước mỗi khi gọi tới tên của local scope nhé.

Dynamic Scopes

Laravel cũng hỗ trợ chúng ta thêm tham số vào local scope mỗi khi chúng ta cần gọi đến ví dụ sau đây tôi sẽ truyền vào local scope một tham số type để thêm value cho ràng buộc của mình:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include users of a given type.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @param  mixed  $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

Sau đó mỗi khi gọi tới tôi chỉ cần thêm giá trị tham số type vào scope

$users = User::ofType('admin')->get();

Dưới đây là một chút chia sẻ về scope trong Laravel. Cảm ơn các bạn đã quan tâm. Tham khảo: https://laravel.com/docs/8.x/eloquent#anonymous-global-scopes

Last updated