我们正在使用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
由于
答案 0 :(得分: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。您必须解析关系查询以尝试 找出添加项目的位置。现在,这些只是简单的例子。我确定有很多东西 复杂的关系在那里是不可能的 解析所有约束和条件以便正确插入 新项目进入现有集合。
现有功能的唯一真正替代方案是 总是强制重新加载现有的加载关系 关系被修改,但这可能会导致一些严重的问题 性能问题。最好确保开发人员知道 如果需要,他们需要明确重新加载关系,而不是 无论是否需要,隐式重新加载它。