多对多关系模型
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
今天谈的是Laravel中一个非要有用,但一开始可能有点难理解的功能。Pivot 表是两个“主表”之间关系的中间表。
Pivot 表实例
在官方文档中,他们用用户-角色(User-Role) 关系来做例子,用户可能会属于多个角色,反之亦然。为了使大家理解的更清楚,我们这里举另一个例子:商店( Shops )与商品( Products )。
我们假设一个商家有多个商店遍布全国各地,并且有各种各样的商品,他们需要存储哪个商品是由哪个商店卖出的信息。这是一个多对多关系非常好的例子:一个商品可以属于多个商店,而一个商店又会有很多的商品。
所以这里就有一个潜在的数据库结构:
shops
– id
– name
products
– id
– name
product_shop
– product_id
– shop_id
列表中最后一个表product_shop就是标题中被称作“pivot”的表。这里有几点需要注意的:
Pivot表的名字应该包含两个表名的单数形式,由下划线分开,并按字母顺序排列,所以我们最终得到的
是product_shop,而不是shop_product。你可以使用artisan make:migration 命令来创建pivot 表,也可以通过Jeffrey Way 的扩展包Laravel 5 Generators Extended 中的artisan make:migration:pivot 命令。Pivot 表字段:默认情况下,只需包含两个字段–分别对应两个表的外键,我们这里
是product_id和shop_id。如果需要的话,你也可以添加跟多字段,后面我们会进行讨论。多对多关系模型:BelongsToMany
我们已经有了数据库表和迁移,现在让我们为它们创建模型。这里主要是分配一个多对多的关系,它可以在任何一个主表模型中定义。
选择1:app/Shop.php class Shop extends Model
{
/**
* The products that belong to the shop.
*/
public function products()
{
return $this->belongsToMany('App\Products');
}
} 选择2:app/Product.php class Product extends Model
{
/**
* The shops that belong to the product.
*/
public function shops()
{
return $this->belongsToMany('App\Shop');
}
}
实际上,你也可以都做,主要是看你在代码中如何使用这个关系–你需要$shop->products 还是$product->shops ,或者两者都需要。
现在的这个声明,Laravel会假设pivot 表命名遵守上面提到的规则,也就是product_shop 。假如不是的话(比如是复数形式),你可以提供第二个参数:
public function products()
{
return $this->belongsToMany('App\Products', 'products_shops');
}
此外,你还可以指定pivot 表中字段的名称,如果它们不用于product_id 和shop_id 。只需要添加两个参数:第一个是(中间表中代表)当前模型的字段,另一个是(中间表中代表)需要关联的模型的字段:
public function products()
{
//shop模型
return $this->belongsToMany('App\Products', 'products_shops',
'shops_id', 'products_id');
}
这里的一个主要好处是,你不需要创建一个单独的ProductShop 模型。
多对多关系管理:attach-detach-sync
现在已经准备好了数据表和模型,那么,现在的问题是我们如果只用两个模型而不用第三个中间模型来保存数据呢?看看下面几点。
例如,我们需要给当前商店(shop>) 实例添加一个商品(product) ,我们可以使用关系函数中的attach() 方法:
$shop = Shop::find($shop_id);
$shop->products()->attach($product_id);
结果就是我们会给product_shop表中添加新的一列,值分别为$product_id 和$shop_id 的值。
相似的,我们也可以解除( detach )一个关系,假设我们把一个商品从商店中移除:
$shop->products()->detach($product_id);
或者更进一步,删除一个特定商店中所有的商品,只需要调用该方法,不传递参数:
$shop->products()->detach();
你可以用过传递数组参数来附加和分离关系:
$shop->products()->attach([123, 456, 789]);
$shop->products()->detach([321, 654, 987]);
另一个非要有用的函数是更新整个pivot 表。一个常见的例子是:管理面板中,一个商品下面有多个商店的多选框,在执行更新操作的时候,需要检查所有的商店,删除新的多选数组中不存在的,并添加或更新有的。一件头疼的事情。
但现在不是了,有一个叫做sync() 的方法,它接受一个数组参数,然后会自动执行完所有的同步工作。
$product->shops()->sync([1, 2, 3]);
结果就是,不管之前product_shop 表中的值是怎么样的,调用该方法之后,只会有shop_id 是1、2、3的三行。
给Pivot 表添加额外列