Laravel模型自定义newQuery函数如何在特定方法中禁用?
解决Laravel模型自定义newQuery无法临时禁用的问题
首先明确:你用without('newQuery')完全没用,因为without()是用来取消模型预加载的关联关系的,和你重写的newQuery方法没有任何关系。
正确方案一:改用官方全局查询作用域(推荐)
Laravel提供了全局查询作用域的机制,专门用来处理这类全局生效的查询条件,并且支持临时禁用。
- 创建作用域类
在app/Scopes目录下创建ExcludeExampleSlugScope.php(没有Scopes目录就新建一个):
namespace App\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; class ExcludeExampleSlugScope implements Scope { public function apply(Builder $builder, Model $model) { $builder->where('slug', '!=', 'example'); } }
- 在模型中注册作用域
修改你的模型类,替换掉原来重写的newQuery方法:
use App\Scopes\ExcludeExampleSlugScope; class YourModel extends Model { // 删掉没用的protected $with = ['newQuery']; 这行是错误的,$with是用来预加载关联的 protected static function booted() { static::addGlobalScope(new ExcludeExampleSlugScope); } }
- 临时禁用作用域
在需要查询包含slug=example数据的方法里,这样调用:
// 只禁用这个特定的作用域 $items = YourModel::withoutGlobalScope(ExcludeExampleSlugScope::class)->get(); // 如果需要禁用所有全局作用域,用这个 // $items = YourModel::withoutGlobalScopes()->get();
方案二:给自定义newQuery加开关(快速生效)
如果不想改全局作用域,可以在模型里加一个静态开关来控制条件是否生效:
修改模型:
class YourModel extends Model { // 全局开关:默认开启排除条件 public static $excludeExampleSlug = true; // 删掉错误的protected $with = ['newQuery']; public function newQuery(){ $query = parent::newQuery(); // 只有开关开启时才添加条件 if (static::$excludeExampleSlug) { $query->where('slug','!=', "example"); } return $query; } }
然后在需要禁用的方法里:
// 临时关闭开关 YourModel::$excludeExampleSlug = false; // 执行查询,此时会包含slug=example的数据 $items = YourModel::get(); // 记得恢复开关,避免影响其他查询 YourModel::$excludeExampleSlug = true;
注意:直接重写
newQuery不是Laravel推荐的做法,容易和框架的其他查询逻辑冲突,优先用全局作用域方案。
内容的提问来源于stack exchange,提问作者Kamal Garu
相关产品推荐
相关产品推荐

