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では のインスタンスが返されるのに対して、2 番目の呼び出しでは のインスタンスが返されることです。$role->permissions()CollectionBelongsToMany

Collection関連するオブジェクトのコレクション (本当に?) でBelongsToManyあり、関係そのものです。そうです、(魔法のプロパティではなく) メソッドを呼び出すことで、データベースにクエリを実行しています。

アップデート

最後の質問がわかりませんでした。最初に (マジック プロパティ) を呼び出すと$role->permissions、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();

ご覧のとおり、最初の例では、クエリを 1 つだけ作成し、結果を別の方法でフィルター処理しています。2 番目の例では、2 つのクエリを作成します。最初のものは明らかにより効率的です。

ただし、同じ実行中にサブセットのみが必要な場合は、状況が変わります。ここでは熱心な読み込みを使用しています:

$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();

ご覧のとおり、2 番目の例ではDRYがはるかに少なく、同じ操作を複数回実行しています。もちろん、効率は悪くなります。

于 2016-08-09T09:27:32.293 に答える