Laravel Eloquent 多对多关系如何实现

4

我想学习Laravel,目前正在尝试使用Eloquent进行实验。

我遇到了一个无法解决的问题:

假设我正在创建一个网店,所以我有商品(Product 1,Product 2等):

+-------------+------------------+------+-----+---------------------+----------------+
| Field       | Type             | Null | Key | Default             | Extra          |
+-------------+------------------+------+-----+---------------------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| name        | varchar(255)     | NO   |     | NULL                |                |
| slug        | varchar(255)     | NO   |     | NULL                |                |
| description | text             | NO   |     | NULL                |                |
| price       | decimal(5,2)     | NO   |     | NULL                |                |
| active      | tinyint(4)       | NO   |     | 1                   |                |
| created_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------+------------------+------+-----+---------------------+----------------+

那些产品被归类到分类法中(品牌、颜色、部门):
+-------------+------------------+------+-----+---------------------+----------------+
| Field       | Type             | Null | Key | Default             | Extra          |
+-------------+------------------+------+-----+---------------------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| name        | varchar(255)     | NO   |     | NULL                |                |
| slug        | varchar(255)     | NO   |     | NULL                |                |
| description | text             | NO   |     | NULL                |                |
| created_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------+------------------+------+-----+---------------------+----------------+

这些分类法有术语(Nike,Adidas,Red,Green,Boys,Girls):

+-------------+------------------+------+-----+---------------------+----------------+
| Field       | Type             | Null | Key | Default             | Extra          |
+-------------+------------------+------+-----+---------------------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| taxonomy_id | int(11)          | NO   |     | NULL                |                |
| name        | varchar(255)     | NO   |     | NULL                |                |
| slug        | varchar(255)     | NO   |     | NULL                |                |
| description | text             | NO   |     | NULL                |                |
| created_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------+------------------+------+-----+---------------------+----------------+

最后,我有一个数据透视表将术语与产品连接起来:

+------------+------------------+------+-----+---------------------+----------------+
| Field      | Type             | Null | Key | Default             | Extra          |
+------------+------------------+------+-----+---------------------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| product_id | int(11)          | NO   |     | NULL                |                |
| term_id    | int(11)          | NO   |     | NULL                |                |
| created_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+------------+------------------+------+-----+---------------------+----------------+

我已经创建了产品(Product)、分类(Taxonomy)和术语(Term)的模型,如下所示:

<?php

class Product extends Eloquent {

    public function terms()
    {
        return $this->belongsToMany('Term', 'product_terms', 'product_id', 'term_id');
    }

}

<?php

class Taxonomy extends Eloquent {

    public function terms()
    {
        return $this->hasMany('Term');
    }

}

<?php

class Term extends Eloquent {

    public function taxonomy()
    {
        return $this->belongsTo('Taxonomy');
    }

}

现在我想要做以下事情:获取所有产品,循环遍历它们,并显示名称、描述和价格等信息。一个简单的 $products = Product::all(); 就足够了。 然后,当我遍历产品时,我知道可以像这样做 $product->terms 来获取所有术语。但是如何获取给定分类法的术语呢?例如类似这样:

<?php
echo $product->term('brand'); // Where 'brand' is the taxonomy name of the term I want to get
echo $product->term('color'); // Where 'color' is the taxonomy name of the term I want to get

希望有人能够帮助我。

1个回答

3

好的,我认为我理解了你的设置。鉴于你所陈述的关系,我认为你可以将你的模型定义如下:

<?php

class Product extends Eloquent {

    public function terms()
    {
        return $this->belongsToMany('Term')->withTimestamps();
    }

}

<?php

class Taxonomy extends Eloquent {

    public function terms()
    {
        return $this->hasMany('Term');
    }

}

<?php

class Term extends Eloquent {

    public function taxonomy()
    {
        return $this->belongsTo('Taxonomy');
    }

    public function products()
    {
        return $this->belongsToMany('Product')->withTimestamps();
    }

}

由于您的数据透视表已正确命名并标识,因此在belongsToMany关系中不需要指定该信息,但如果您想使时间戳有效,则需要使用withTimestamps。

编辑:

如果您可以通过id而不是slug查找分类法,那么这将起作用:

$products = Product::all();
foreach($products as $product)
{
    $term = $product->terms()->with('taxonomy')->where('taxonomy_id', '=', 2)->first();
    echo $term->name;
}

在上述场景中,您可以在术语表中仅存储分类法slug,因为它应该是唯一的键。否则,您可以查看术语并查找所需分类法的术语:
$products = Product::all();
foreach($products as $product)
{
    $terms = $product->terms()->with('taxonomy')->get();
    foreach($terms as $term)
    {
        if($term->taxonomy->slug == 'brand')
        {
            echo $term->name."<br />";
        }
    }
}

编辑结束

我必须承认,我有点迷惑,因为你最后两个表格看起来完全相同,我想知道为什么你把术语与产品关联起来,而不是将分类法与产品关联起来。我怀疑我的解决方案不能适用于你关联事物的方式,但如果你将分类法与产品相关联,它就能正常工作。

<?php
$product->taxonomy()->where('slug', '=', 'brand')->term;

每个产品都有一堆分类法,每个分类法都有一个术语。因为你想知道像“产品是什么颜色”的事情,所以你想将分类法与产品关联起来,而不是术语。出于好奇,如果您删除括号,它是否有效?$product->terms->taxonomy()->where('slug', '=', 'brand')->first(); 或 $product->terms()->taxonomy->where('slug', '=', 'brand')->first(); 或 $product->terms->taxonomy->where('slug', '=', 'brand')->first(); 或者从结尾去掉第一个。 - Beau
我认为你只需要像这样做:foreach($product->taxonomies as $taxonomy) { echo $taxonomy->term->name; } 一双鞋子没有“红色”,它是一种颜色,可能是红色。此外,关于错误中的“$taxonomy”部分似乎有些可疑,也许是你类定义中的一个错误。 - Beau
我的意思是它“有”一种颜色,而不是它“是”一种颜色。红色显然是一种颜色。这样做可以吗?$taxonomy = $product->term('brand')->with('taxonomy'); echo $taxonomy->name; - Beau
只是为了明确,$product 在你看来是什么?它是由 $products = Product::all(); 返回的所有产品进行 foreach 循环后的结果,就像 foreach($product as $product) { // your code } 这样。 - Crinsane
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Crinsane
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接