Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Добрый день, объясните пожалуйста данное поведение:
$items = Item::where('some', '=', 1);
$items->get();
$items = Item::where('some', '=', 1);
$items->take(10);
$items->get();
$items = Item::where('some', '=', 1);
$things = clone $items;
$things->take(10);
$items->get();
вернет 10 записей? Я ведь установил лимит $things, а не $items. Заранее спасибо!
Не в сети
По всей видимости ты используешь Eloquent (PHPItem = Laravel\Database\Eloquent\Model
). Когда ты начинаешь запрос (PHP::where()
) ты получаешь объект класса PHPLaravel\Database\Eloquent\Query
— это обёртка над PHPLaravel\Database\Query
. Соответственно, при клонировании ты клонируешь обёртку, но её поля PHP$model
(здесь — PHPItem
) и PHP$table
(тот самый PHPQuery
) остаются старыми. Когда ты делаешь PHPtake(10)
ты изменяешь именно объект внутри PHP$table
, который и «переживает» клонирование. В итоге у тебя получается два объекта Query Eloquent, которые внутренне привязаны к одному запросу.
Могу посоветовать такой вариант:
$items = Item::where('some', '=', 1);
$things = clone $items;
$things->table = clone $things->table;
$things->take(10);
$items->get();
Хотя, конечно, лучше всего бы это исправить в ядре через PHP__clone()
, чтобы не писать так каждый раз.
Не в сети
$things = clone $items;
$things->table = clone $things->table;
Это порнография, сами понимаете. В любом случае у меня PHPclass Model extends Eloquent
, в ядро я стараюсь не лазить.
Но на для подстраховки уточню:
class Model extends Eloquent {
function __clone() {
$this->table = clone $this->table;
}
}
Это допустимая конструкция? Я ничего не перекрываю?
Спасибо большое за разъяснение архитектуры! Вы, должно быть, структуру наизусть знаете.
Не в сети
- Это порнография, сами понимаете.
Естественно. Поэтому вариант — или менять ядро (чего я избегаю всеми методами), или добавлять метод. Собственно, в данном случае последнее вполне возможно.
Тем не менее, прежде чем реализовывать полноценное исправление советую всё же проверить, работает ли мой пример, так как сам я его не пробовал.
- Это допустимая конструкция? Я ничего не перекрываю?
Конструкция допустимая, только метод не в том классе. Как я описал выше, при вызове любого метода запроса на классе модели возвращается не объект этой модели, а объект запроса. В твоём примере расширяется именно модель, а это не то что нужно.
Из-за архитектуры Eloquent вопрос решается двумя частями: нужно расширить класс запроса, но кроме этого — перекрыть метод в PHPEloquent
(он же — PHPLaravel\Database\Eloquent\Model
), который возвращает наш перекрытый объект запроса, а не стандартный PHPLaravel\Database\Eloquent\Query
без PHP__clone
.
class Model extends Eloquent {
function query() {
return new EloquentQueryEx($this);
}
}
class EloquentQueryEx extends Laravel\Database\Eloquent\Query {
function __clone() {
$this->table = clone $this->table;
}
}
Не в сети
, прочитал все понял, и написал глупость. Прошу прощения, был вечер. Единственное уточнение, что бы не заморачиваться с длинными именами свой класс назвал просто Query, в application.php/aliases это имя свободно, так что, думаю, проблем не будет. Правильно?
class Query extends Laravel\Database\Eloquent\Query {
function __clone() {
$this->table = clone $this->table;
}
}
Не в сети
Не в сети