我需要重写上述方法以跳过一些数据库记录。不能选择使用where
,因为我必须每次都使用它,因为数据库中有很多记录我不需要大部分时间,并且不允许将它们从数据库中删除。这是我这样做的尝试:
class SomeTable extends BaseModel {
public static function first() {
$query = static::query();
$data = $query->first();
if($data && $data->type == 'migration_type') return null;
return $data;
}
public static function get() {
$query = static::query();
$data = $query->get();
foreach($data as $key => $item) {
if($item->type == 'migration_type') unset($data[$key]);
}
return $data;
}
}
此代码的问题在于它仅在直接调用模型时才有效。如果我在where
或get
方法之前使用其他功能,例如first
,它会跳过我的重写方法。
什么是正确的方法,我应该将此代码放在模型中吗?
我的问题不是重复的,因为提到的问题的答案是这样的:
通过模型扩展您的CustomModel进行的所有查询都将获得此新方法
我只需要为特定模型覆盖这两个函数,而不是为应用程序中的每个模型覆盖这两个函数,因为并非所有表都具有type
列。这就是为什么我在模型类中编写它们的原因。
答案 0 :(得分:4)
我需要重写上述方法以跳过一些数据库记录。
考虑模型的全局查询范围。
https://laravel.com/docs/5.8/eloquent#global-scopes
全局作用域允许您向给定模型的所有查询添加约束。 Laravel自己的软删除功能利用全局作用域仅从数据库中提取“未删除”模型。编写自己的全局范围可以提供一种简便的方法,以确保针对给定模型的每个查询都受到某些约束。
答案 1 :(得分:0)
因为在调用您要与数据库构建器打交道的地方之后,并且未在模型中调用这些方法..关于该问题,您可以通过直接使用select
而不是first
来解决该问题所以将与建造者打交道..
示例:
SomeTable::select('col1','col2')->take(1)->get();
如果您与同一个项目的其他开发人员一起工作,则覆盖此类方法的另一件事不是一个好主意。
祝你好运
答案 2 :(得分:0)
这里的问题是模型上的where()方法返回一个QueryBuilder
实例,而get()将返回一个Collection
实例。
您应该能够通过在其位置添加一个宏来覆盖collection的默认方法,并且可以这样做...
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
扩展查询生成器实例并不容易,但是存在一个不错的教程here,其中涉及到覆盖应用程序的默认连接类,这在以后的升级中不是很好。