Мы разрабатываем корзину для электронной коммерции, используя Laravel 5.3, в которой есть предметы. Таким образом, наша корзина имеет отношение 1: n к товарам.
Когда мы добавляем продукт в корзину, используя Illuminate\Database\Eloquent\Relations\HasOneOrMany::save()
это не подталкивает новый предмет к нашему $cart->items
сбор, это должно быть сделано вручную с помощью Collection::push()
метод.
Мы просим об этом, потому что Illuminate\Database\Eloquent\Relations\BelongsTo::associate()
Метод делает это, поэтому мы не знаем, если это ошибка.
Просто для лучшего понимания:
Теперь нам нужно сделать это:
$cart = Cart::first();
$cartItem = new CartItem();
$cartItem->quantity = 1;
$cartItem->base_price = 1;
$cartItem->paid_price = 1;
$cart->items()->save($cartItem);
print($cart->items->count()); # returns 0
$cart->items->push($cartItem);
print($cart->items->count()); # returns 1
То, что мы хотим сделать, — это приведенный выше код, а затем иметь возможность взаимодействовать с нашим списком (например, обновлять значения порядка), не вызывая другие методы.
$cart = Cart::first();
$cartItem = new CartItem();
$cartItem->quantity = 1;
$cartItem->base_price = 1;
$cartItem->paid_price = 1;
$cart->items()->save($cartItem);
print($cart->items->count()); # returns 1
Мы думаем о том, чтобы сделать запрос на извлечение, потому что мы видели код, и это можно сделать. Но правильно ли это? Можем ли мы сделать это?
Дублируется отсюда: https://github.com/laravel/framework/issues/14719
Спасибо
Вы можете быть заинтересованы в обсуждении Эта проблема. Я скопировал комментарии, которые я сделал по этому вопросу здесь, на случай, если эта ссылка исчезнет в какой-то момент.
Информация о том, как загружаются атрибуты отношений:
Это ожидаемое поведение. После того, как атрибут отношения для модели
экземпляр загружен, он не будет перезагружен, если явно
перезагружается.// relationship attribute lazy loaded here $blog->posts->count() $post = new Post(['title' => 'post title'); // typo in OP; save() must be called on relationship method, not relationship attribute $blog->posts()->save($post); // relationship already loaded. Collection has not changed. $blog->posts->count(); // 0 // however, call to database will reflect current count $blog->posts()->count(); // 1 // reload the relationship attribute $blog->load('posts'); // relationship collection refreshed; count of relationship attribute will reflect this $blog->posts->count(); // 1
Почему атрибут отношения Collection
не обновляется при добавлении элемента в отношение:
Я думаю, что слишком много неопределенности, чтобы попытаться изменить
Коллекция. Даже если вы связываете пост с блогом через
posts()
отношения, нет никакой гарантии, что новый пост
должен быть загружен в атрибут отношения Collection в
первое место.Представьте, например, если ваши отношения были определены так
(глупый пример, но терпите меня)// only get posts created before today public function posts() { return $this->hasMany(Post::class)->where('created_at', '<', date('Y-m-d')); }
Учитывая эти отношения, так как новый пост создается сегодня, он будет
быть неверным, если он был просто введен в существующий ленивый загруженный
$blog->posts
сбор, потому что он не соответствует добавленной где
состояние. Если вы перезагрузите эти отношения, новый пост все равно
не быть в этом.Другой пример будет следующим:
// get the posts, newest first public function posts() { return $this->hasMany(Post::class)->orderBy('created_at', 'DESC'); }
Учитывая это отношение, если новый пост добавляется в конец
существующие загружены$blog->posts
коллекция, это будет в неправильном
порядок. Можно утверждать, что это можно добавить к началу, но
тогда это было бы в неправильном порядке, если бы отношения были
заказал ASC. Вы должны были бы проанализировать запрос отношения, чтобы попытаться
выяснить, где добавить элемент.Теперь это просто простые примеры. Я уверен, что есть много очень
сложные отношения там, где было бы невозможно
проанализировать все ограничения и условия, чтобы правильно вставить
новый предмет в существующую коллекцию.Единственной реальной альтернативой существующей функциональности будет
всегда принудительно перезагружать существующие загруженные отношения всякий раз, когда
отношения изменяются, однако это может привести к серьезным
проблемы с производительностью. Кажется, лучше убедиться, что разработчик знает
они должны явно перезагрузить отношения, если это необходимо, а не
неявно перезагрузить его, нужно ли это или нет.
Других решений пока нет …