You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Query Builder能否应用全局或本地作用域?

在Laravel Query Builder中实现作用域(类似Eloquent)

当然可以在Query Builder中实现类似Eloquent的全局/本地作用域,以下是针对软删除场景的具体实现方式:

一、本地作用域(可复用查询片段)

Query Builder没有Eloquent的scopeXXX自动识别机制,但可以通过**自定义宏(Macro)**实现可复用的查询逻辑:

  1. 在App\Providers\AppServiceProvider的boot方法中定义宏:
use Illuminate\Database\Query\Builder;

public function boot()
{
    // 定义仅查询未软删除数据的宏
    Builder::macro('withoutTrashed', function () {
        return $this->whereNull('deleted_at');
    });

    // 定义查询包含软删除数据的宏
    Builder::macro('withTrashed', function () {
        return $this->whereNotNull('deleted_at')->orWhereNull('deleted_at');
    });

    // 自定义业务作用域:查询活跃且未删除的用户
    Builder::macro('activeAndNotDeleted', function () {
        return $this->where('is_active', 1)->withoutTrashed();
    });
}
  1. 使用方式:
// 查询未删除的用户
DB::table('users')->withoutTrashed()->get();

// 查询活跃且未删除的用户
DB::table('users')->activeAndNotDeleted()->get();

二、全局作用域(自动应用到所有Query Builder查询)

如果希望所有Query Builder查询默认自动排除软删除数据,可通过以下两种方式实现:

方式1:重写Query Builder默认查询逻辑

在AppServiceProvider的boot方法中修改Builder的默认行为:

use Illuminate\Database\Query\Builder;

public function boot()
{
    // 保存原生newQuery方法
    $originalNewQuery = Builder::getMacro('newQuery');
    
    Builder::macro('newQuery', function () {
        // 调用原生方法后自动添加软删除约束
        return $originalNewQuery()->whereNull('deleted_at');
    });

    // 提供取消全局约束的方法
    Builder::macro('withTrashed', function () {
        // 移除deleted_at的null约束
        $this->wheres = collect($this->wheres)->reject(function ($where) {
            return $where['column'] === 'deleted_at' && $where['operator'] === 'null';
        })->values()->all();
        return $this;
    });
}

此后所有DB::table('xxx')的查询都会自动带上whereNull('deleted_at'),需要包含软删除数据时调用withTrashed()即可。

方式2:自定义Query Builder类

创建继承自原生Builder的自定义类,在构造方法中默认添加软删除约束:

namespace App\Database\Query;

use Illuminate\Database\Query\Builder as BaseBuilder;

class SoftDeleteBuilder extends BaseBuilder
{
    public function __construct($connection, $grammar = null, $processor = null)
    {
        parent::__construct($connection, $grammar, $processor);
        // 默认添加软删除约束
        $this->whereNull('deleted_at');
    }

    // 取消软删除约束,查询所有数据
    public function withTrashed()
    {
        $this->wheres = collect($this->wheres)->reject(function ($where) {
            return $where['column'] === 'deleted_at' && $where['operator'] === 'null';
        })->values()->all();
        return $this;
    }

    // 仅查询软删除的数据
    public function onlyTrashed()
    {
        $this->withTrashed();
        return $this->whereNotNull('deleted_at');
    }
}

在AppServiceProvider的register方法中绑定自定义Builder:

use App\Database\Query\SoftDeleteBuilder;
use Illuminate\Database\Connection;

public function register()
{
    $this->app->resolving(Connection::class, function (Connection $connection) {
        $connection->setQueryBuilder(new SoftDeleteBuilder(
            $connection,
            $connection->getQueryGrammar(),
            $connection->getPostProcessor()
        ));
    });
}

使用方式与原生Query Builder完全一致:

// 默认查询未删除数据
DB::table('users')->get();

// 查询包含软删除的数据
DB::table('users')->withTrashed()->get();

// 仅查询软删除的数据
DB::table('users')->onlyTrashed()->get();

内容的提问来源于stack exchange,提问作者Shahzad Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:55:11