1

我是否正确地知道当我查询 Laravel 集合时,它不会查询数据库,而是对已经获取的内容执行查询?

例如,我有一个返回集合的关系:

public function permissions()
{
    return $this->belongsToMany(Permission::class, RolePermission::getModelTable(), 'role_id', 'permission_id');
}

以下代码是查询数据库还是使用 php 工具与集合一起工作?

$role->permissions->where('code','global.test')->count()

而且,据我了解,如果我查询关系,则将查询数据库,而不是使用已经获取的结果:

$role->permissions()->where('code','global.test')->count()

所以基本上,$role->permissions - 使用“离线”获取的结果,但$role->permissions() - 查询数据库

什么方式通常更有效,什么时候?

4

1 回答 1

3

你基本上是对的。$role->permissions调用和之间的区别在于$role->permissions(),第一个返回 的实例Collection,而第二个返回 的实例BelongsToMany

Collection是相关对象的集合(真的吗?)并且BelongsToMany是关系本身。所以是的,通过调用方法(而不是魔法属性),您正在查询数据库。

更新

最后一个问题我没听懂,抱歉。第一次调用$role->permissions(magic property) 时,Laravel 会获取与 关联的所有权限$role,如果它们不是预先加载的。如果您只需要这些权限的一个子集,您可以使用任何魔法属性和方法来过滤它们。让我举几个例子。

$role = Role::first();
// Fetch all the permissions and count a subset.
$role->permissions->where('code', 'global.test')->count();
// Count another subset.
$role->permissions->where('code', 'another.test')->count();

可以使用以下方法完成相同的操作:

$role = Role::first();
// Fetch a subset of the permissions and count it.
$role->permissions()->where('code', 'global.test')->count();
// Fetch another subset and count it.
$role->permissions()->where('code', 'another.test')->count();

如您所见,在第一个示例中,您只进行一次查询并以不同方式过滤结果。在第二个示例中,您进行了两个查询。第一个显然更有效。

但是,如果您在同一执行期间只需要一个子集,情况就会发生变化。这里我们使用急切加载

$role = Role::with('permissions', function($query) {
    // Here we filter the related permissions.
    $query->where('code', 'global.test');
})->first();
// We have what we want. No need to filter the collection.
$role->permissions->count();
// Let's do something else with this subset.
$role->permissions->all();

如果您获取所有相关对象,但只需要该子集怎么办?

$role = Role::first();
// Filter the collection to count the needed subset.
$role->permissions->where('code', 'global.test')->count();
// Filter the collection to get the needed subset.
$role->permissions->where('code', 'global.test')->all();

如您所见,在第二个示例中,我们的DRY少得多,而且我们还多次执行相同的操作。当然,效率较低。

于 2016-08-09T09:27:32.293 回答