Laravel的 Eloquent ORM 中Scopes和accotiate()

在 Laravel 的 Eloquent ORM 中,Scopes(作用域)是一种用于封装数据库查询逻辑的便捷方式。Scopes 可以帮助你在模型中定义常用的查询逻辑,并使其在需要时更易于重用和调用。

Scopes 有两种类型:全局作用域(Global Scopes)和局部作用域(Local Scopes)。

局部作用域(Local Scopes)

局部作用域是一种在模型中定义的查询方法,你可以通过调用这个方法来应用特定的查询逻辑。

定义局部作用域

你可以在模型中定义一个局部作用域方法。局部作用域方法的名称应该以 scope 开头,并且在调用时不需要包括 scope 前缀。

例如,在 User 模型中定义一个 scopeActive 局部作用域:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // 定义一个局部作用域来筛选激活的用户
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

使用局部作用域

使用局部作用域时,只需在查询中调用不带 scope 前缀的方法:

use App\Models\User;

// 获取所有激活的用户
$activeUsers = User::active()->get();

你还可以将多个作用域链式调用:

// 定义另一个作用域来筛选管理员用户
public function scopeAdmin($query)
{
    return $query->where('role', 'admin');
}

// 获取所有激活的管理员用户
$activeAdmins = User::active()->admin()->get();

全局作用域(Global Scopes)

全局作用域是你希望在模型的所有查询中自动应用的查询逻辑。定义全局作用域时,你需要创建一个实现 Scope 接口的类,并在模型中注册该作用域。

定义全局作用域

创建一个全局作用域类:

namespace App\Scopes;

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

class ActiveScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('active', 1);
    }
}

注册全局作用域

在模型中注册全局作用域:

namespace App\Models;

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

class User extends Model
{
    protected static function booted()
    {
        static::addGlobalScope(new ActiveScope);
    }
}

使用全局作用域

全局作用域会自动应用于所有的查询:

use App\Models\User;

// 获取所有激活的用户
$users = User::all(); // 仅返回激活的用户

如果你想在特定查询中忽略全局作用域,可以使用 withoutGlobalScope 方法:

use App\Models\User;
use App\Scopes\ActiveScope;

// 获取所有用户,包括未激活的用户
$allUsers = User::withoutGlobalScope(ActiveScope::class)->get();

总结

  • 局部作用域:在模型中定义以 scope 开头的方法,用于封装特定的查询逻辑,调用时省略 scope 前缀。
  • 全局作用域:创建一个实现 Scope 接口的类,并在模型中注册该作用域,自动应用于所有查询。

使用作用域可以使你的查询逻辑更加清晰、可重用,并且更易于维护。

accotiate()

associate() 方法是 Laravel 的 Eloquent ORM 中的一个功能强大的方法,用于在两个模型之间建立关联关系。它通常用于处理多对多(Many-to-Many)的关系。

让我们通过一个示例来更好地理解 associate() 方法的用法。假设我们有两个模型:UserRole。每个用户可以有多个角色,每个角色也可以被多个用户拥有。这就是一个典型的多对多关系。

首先,我们需要在两个模型中定义关联关系。在 User 模型中:

public function roles()
{
    return $this->belongsToMany(Role::class);
}

Role 模型中:

public function users()
{
    return $this->belongsToMany(User::class);
}

现在,假设我们有一个用户实例 $user 和一个角色实例 $role。我们可以使用 associate() 方法将这个角色与用户建立关联关系:

$user->roles()->associate($role);
$user->save();

这个过程实际上做了以下几件事:

  1. 在中间表(通常命名为 role_user)中插入一条新记录,将 $user 的 ID 和 $role 的 ID 关联起来。
  2. 保存 $user 模型实例,确保关联关系被持久化到数据库中。

如果我们想要删除某个用户与某个角色之间的关联关系,可以使用 detach() 方法:

$user->roles()->detach($role);
$user->save();

这将从中间表中删除对应的记录,断开两个模型之间的关联关系。

除了 associate()detach() 方法,Eloquent 还提供了其他一些方法来管理多对多关系,例如:

  • sync(): 同步关联关系,替换现有的关联。
  • toggle(): 切换关联关系,如果存在则删除,如果不存在则添加。
  • attach(): 添加新的关联关系。

总的来说,associate() 方法是 Eloquent 中管理多对多关系的一个重要工具,它可以帮助开发者更方便地建立和维护模型之间的复杂关联关系。

posted @ 2024-05-15 10:24  Laravel自学开发  阅读(88)  评论(0编辑  收藏  举报