Vadiok
2/29/2016 - 10:43 AM

Laravel: correct copying of Eloquent objects with queries.

Laravel: correct copying of Eloquent objects with queries.

Правильный способ копирования Eloquent объекта

Чтобы правильно скопировать Eloquent объект с примененным условиями where для последующего использования в построении разных запросов в нескольких переменных, необходимо клонировать объект вместо простого копирования:

<?php
// Родительское ограничение, требуемое для обоих запросов
$parentQuery = SomeModel::where('some_field', 'some_value');
$childQuery = clone $parentQuery;
$childQuery->where('another_field', 'another_value');
// ... Other actions
$anotherChildQuery = clone $parentQuery;

Пример

Делаем выборку на основе модели SomeModel, ограниченную в обоих случаях user_id=5, status=10 - в 1-м случае, status=20 - во 2-м случае.

Правильный вариант - клонирование:

<?php
// Родительское ограничение, требуемое для обоих запросов
$userLimitQuery = SomeModel::where('user_id', 5);
$itemsOfStatus10QueryBuilder = clone $userLimitQuery;
$itemsOfStatus20QueryBuilder = clone $userLimitQuery;

// То же, что и SomeModel::where('user_id', 5)->where('status', 10)->get();
// Результат - коллекция объектов со статусом 10 у пользователя 5
$status10Items = $itemsOfStatus10QueryBuilder->where('status', 10)->get();

// То же, что и SomeModel::where('user_id', 5)->where('status', 20)->count();
// Результат - число записей со статусом 20 у пользователя 5
$status20Count = $itemsOfStatus20QueryBuilder->where('status', 20)->count();

Неправильный вариант - копирование

<?php
// Родительское ограничение, требуемое для обоих запросов
$userLimitQuery = SomeModel::where('user_id', 5);
$itemsOfStatus10QueryBuilder = $userLimitQuery;
$itemsOfStatus20QueryBuilder = $userLimitQuery;

// То же, что и SomeModel::where('user_id', 5)->where('status', 10)->get();
// Результат верный - коллекция объектов со статусом 10 у пользователя 5
$status10Items = $itemsOfStatus10QueryBuilder->where('status', 10)->get();

// То же, что и SomeModel::where('user_id', 5)->where('status', 10)->where('status', 20)->count();
// Результат неверный - 0, т.к. к текущей выборке добавилось ограничение из предыдущего запроса
$status20Count = $itemsOfStatus20QueryBuilder->where('status', 20)->count();