如何在使用Eloquent时排除某些列

14 浏览
0 Comments

如何在使用Eloquent时排除某些列

当我使用eloquent时,我可以使用"where"方法,然后使用"get"方法来填充一个包含我在数据库中选择的内容的对象。

我的意思是:

$users = User::where('gender', 'M')->where('is_active', 1)->get(['pseudo', 'email', 'age', 'created_at'])->toArray();

在这里,我可以选择我想要获取的列,比如'pseudo','email'等等...

但是我在laravel文档中缺少相反的方法。

可能是这样的:

$users = User::where('gender', 'M')->where('is_active', 1)->notGet(['pseudo', 'email', 'age', 'created_at'])->toArray();

谢谢您未来的回答,祝您有个愉快的一天。

0
0 Comments

在使用Eloquent时如何排除某些列

在Laravel 5.4中,你可以在User模型中添加以下代码:

protected $hidden = ['pseudo', 'email', 'age', 'created_at'];

然后,User::find(1);将返回除了, , 之外的所有字段。

但是,你仍然可以通过以下方式检索这些隐藏字段:

$user = User::find(1);
$email = $user['email']; // or $user->email;

这个功能在Laravel 5.1中也可用。

它将隐藏字段从输出中隐藏(toArray(),toJSON()),但仍然从数据库加载。因此,当你不想加载某些数据时,这种方法是无用的。

如果你在模型中有某些数据,默认情况下不想加载它,那么你应该拆分资源并使用关系。

我不同意这种说法。拆分资源并使用关系是一种非常困难的解决方案,只适用于最复杂的情况。在现实生活中,仅加载当前所需的列是一项非常常见的任务。例如,可能有一个很重的列,它只在加载单个模型时才是必需的,但在加载所有模型时不是必需的。跳过它可以节省很多内存。

我只部分同意这种说法。我理解你的观点,但我认为限制数据集的责任应该由集合承担,这样你就可以处理大量数据/在只使用特定字段时节省计算资源。模型应该是可预测和原子的,对于仍然需要它的特殊情况,有许多方法可以过滤对象/通过直接查询/构建器加载它。如果你的模型中有[特别大的]数据字段,你通常不想加载它,那么它可能应该放在一个单独的模型中。

0
0 Comments

在使用Eloquent时如何排除某些列?

在使用Eloquent时,我们可以使用模型中的hidden数组来隐藏某些列,但是如果您不想始终隐藏该列,并且想要在需要时使用makeVisible来访问它们,那么您可以在需要时使用makeHidden函数隐藏列的序列化,就像这样:

$res = Model::where('your query')->get();
$res->makeHidden(['column_one','column_two','column_n']);
return response()->json($res);

但是,如果该列很大,这种方法就没有用了,因为您仍然会查询它,而我们的目标是不查询它。我有一个包含几百KB数据的形状几何列的表,我需要调用该模型的大约100个对象,我需要在查询中排除它。

根据使用情况,我需要隐藏created_at,updated_at和deleted_at这三个字段,上述答案对我来说是最完美的解决方法。

如果您想要隐藏序列化中的某个字段,这个答案是最好的解决方法。

这对我来说也是最好的解决方案。您还可以像这样对它们进行序列化:

Model::first()->relationship->makeHidden(['field1', 'field2']);

但如果您遇到了"Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::makeHidden()"的错误,那是因为这个答案已经过时了,您可以在最新版本的文档中找到有关这个方法的详细信息:[laravel.com/docs/8.x/eloquent-collections#method-makeHidden](https://laravel.com/docs/8.x/eloquent-collections#method-makeHidden)

所以,您可以使用以下代码来排除某些列:

User::where("id", 1)->get()->makeHidden(['accessPermission', 'verification_timestamp']);

以上就是如何在使用Eloquent时排除某些列的原因和解决方法。

0
0 Comments

在使用Eloquent时如何排除某些列

有时候你可能只需要隐藏模型数组或JSON表示中的某些属性,你可以使用以下一种或两种方法:

1. 将`$hidden`属性添加到你的模型中:

class User extends Model
{
    /**
     * The attributes that should be hidden for arrays.
     */
     protected $hidden = ['password'];
}

2. 使用`makeHidden`函数:

$users = $users->makeHidden(['address', 'phone_number']);

但是,有时候你不想将庞大的数据(如地理空间数据、HTML、日志等)加载到应用程序中,这样会导致速度变慢并占用更多的内存。虽然OP要求的是一个SQL查询,但大多数情况下,只隐藏JSON响应中的数据更方便。

目前,我了解到SQL中没有内置选项来明确排除列,所以Laravel无法做到。但你可以尝试使用这个技巧:[https://stackoverflow.com/questions/9122](https://stackoverflow.com/questions/9122)

更新:

另一个技巧是在你的模型中指定所有列,然后添加一个本地作用域函数。你可以使用`$this->getTableColumns()`来获取所有列,具体可以参考[这个答案](https://stackoverflow.com/a/56425794/3192276)。你也可以在每次迁移后将其缓存起来,以避免两次查询。

// 下面的代码需要你在$columns中定义所有的列。
// 一个更好的方法是查询表的结构,并在每次迁移后将其缓存,具体请参考:[https://stackoverflow.com/a/56425794/3192276](https://stackoverflow.com/a/56425794/3192276)
protected $columns = ['id','pseudo','email'];
public function scopeExclude($query, $value = [])
{
    return $query->select(array_diff($this->columns, (array) $value));
}

然后你可以这样使用:

$users = User::where('gender', 'M')
    ->where('is_active', 1)
    ->exclude(['pseudo', 'email', 'age', 'created_at'])
    ->toArray();

请注意,`->exclude`会导致方法不被允许。上面的模型函数`scopeExclude()`是这样调用的。可以在[laravel.com/docs/5.3/eloquent#local-scopes](https://laravel.com/docs/5.3/eloquent#local-scopes)上了解有关Laravel作用域的更多信息。

这种方法在与[https://laravel.com/docs/5.4/eloquent-relationships#eager-loading](https://laravel.com/docs/5.4/eloquent-relationships#eager-loading)链式关系加载一起使用时无效:模型本身返回正确的列,但关系无法检索到。

我不确定我是否理解你的问题,但在大多数情况下,如果关系无法检索到,那么你在模型本身没有选择主键。因此,如果主键是`id`列,请不要排除它,因为Laravel在内部使用它进行映射。

`$this->columns`似乎不再起作用,返回null。它仍然在Laravel5.7 php7.3上工作,请确保你没有覆盖`$columns`属性。

对于较新的版本,如Laravel 8,是否有任何绕过方法,而不是使用`Schema::getColumnListing('table')`从数据库模式中加载列?

我不知道是否有其他绕过方法,正如我所说的,这是一个SQL的限制,所以Laravel无法一次性完成。在所有DBMS中,总体共识是查询模式,所以你可以定义一个SQL函数、过程或视图...你也可以缓存`Schema::getColumnListing('table')`的结果,并在每次迁移时清除它,这样就避免了额外的SQL查询。

嘿,我已经更新了我的答案,增加了缓存的支持。

0