2016-08-10 10 views
1

Мы разрабатываем электронную коммерческую корзину, используя Laravel 5.3, в которой есть элементы. Таким образом, наша тележка имеет отношение 1: n к элементам.Почему HasOneOrMany не обновляет отношения с родителями?

Когда мы добавляем товар в корзину с помощью 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 

Что мы хотим сделать это выше код, а затем быть в состоянии interate с нашим списком (например, обновление значения порядка), не вызывая других методов.

$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

Благодаря

ответ

1

Вы можете быть заинтересованы в обсуждении this issue. Я скопировал комментарии, которые я сделал по этой проблеме, в случае, если ссылка в какой-то момент уйдет.

Информация о том, как атрибуты отношения загружены:

Это ожидаемое поведение. Как только атрибут отношения для экземпляра модели загружен, он не будет перезагружен, если явно не перезагрузится .

// 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. Вы должны проанализировать запрос отношения, чтобы попытаться установить , где можно добавить элемент.

Теперь это простые примеры. Я уверен, что существует очень много сложных отношений там, где было бы невозможно разобрать все ограничения и условия, чтобы правильно вставить новый элемент в существующую коллекцию.

Единственная реальная альтернативой существующей функциональности будет всегда принудительной перезагрузкой существующих загруженных отношений, когда модифицируются отношений, однако это может привести к серьезным проблем с производительностью. Лучше всего убедиться, что разработчик знает им необходимо явно перезагрузить связь, если необходимо, вместо , чтобы неявно перезагрузить его, нужно ли это или нет.