如何在laravel中获取多对多关系项

Posted

技术标签:

【中文标题】如何在laravel中获取多对多关系项【英文标题】:How to get many to many relationship items in laravel 【发布时间】:2016-10-03 05:47:54 【问题描述】:

有一个网店的数据结构:

Series -> (many to many) -> categories -> (many to many) -> products

例如,系列为“户外系列”,类别为“T恤”,产品为“T恤A、T恤B等……”

这是列出一个类别中的产品的控制器

public function view($series = 0, $cat = 0, $page = 1) 
        $category = Category::find($cat);

        $totalItems = count($category->product);
        $itemsPerPage = 30;
        $currentPage = $page;
        $urlPattern = "/ums/product/view/$series/$cat/(:num)";

        $this->data['product_list'] = $category->product()->orderBy('created_at', 'desc')->skip(($page - 1) * $itemsPerPage)->take($itemsPerPage)->get();
        $this->data['paginator'] = new Paginator($totalItems, $itemsPerPage, $currentPage, $urlPattern);
        $this->data['category'] = $category;
        $this->data['page'] = $page;
        return view('product/list')->with($this->data);
    

现在,问题是,我想重写代码,这样我就不想显示一个类别,而是想显示一个系列。

这意味着如果 $series = 0 ,那么它显示一个类别中的产品,如果 $cat = 0,那么它显示 multi 类别中的产品

在 laravel 中如何获取多类别的产品?尝试 $series->category->product() 但没有运气,如何重写该函数以支持显示系列?

非常感谢。

【问题讨论】:

有时候 laravel 没那么雄辩吧 $series->category->product() 出了什么问题,结果是什么? 【参考方案1】:

假设 Laravel 模型类 - 系列、类别和产品

对于系列模型类,创建一个函数

   public function categories()
   
        return $this->belongsToMany('App\Category');
   

对于Category Model Class,创建一个函数

   public function products()
   
        return $this->belongsToMany('App\products');
   

现在,对于给定的系列,您可以使用 简单的函数调用

$categories = $series->categories();

终于来到了在多个类别下展示产品的主要问题。

for($categories as $category)

     $productsOfThisCategory = $categories->products();
     //save into some other data structure, say an array $allProducts

$allProducts 将具有特定系列的多类别产品。

参考:Standard eloquent relationship -Many to Many

【讨论】:

谢谢,多类下单如何处理? 将 $category->products() 函数调用扩展到 $category->products()->orderBy('field_name') 或 $category->products()->orderBy('field_name' , 'desc') 根据要求。【参考方案2】:

您可以使用此答案进行排序。

How to sort by a field of the pivot table of a many-to-many relationship in Eloquent ORM

【讨论】:

【参考方案3】:

如果我理解正确,那么您的模型如下所示

class Series extends Model


    // other code

    public function categories() 
        return $this->belongsToMany('App\Category');
    

    // other code


class Category extends Model


    // other code

    public function series() 
        return $this->belongsToMany('App\Series');
    

    public function products() 
        return $this->belongsToMany('App\Product');
    

    // other code


class Product extends Model


    // other code

    public function categories() 
        return $this->belongsToMany('App\Category');
    

    // other code

进一步获取某些系列的所有产品你需要这样做

public function view($series = 0, $cat = 0, $page = 1)

    if (!empty($series)) 
        $seria = Series::with(['categories' => function($query) 
            $query->with('products');
        )->find($series);
        // or may be this will work, don't know
        // Series::with('categories.products')->find($series);

        // get all caegories from seria or certain one
        if (empty($cat)) 
            $categories = $seria->categories; 
        
        else 
            $categories = $seria->categories()->where('id', $cat)->get; 
        

        // retrieve produts form each category and making from them collection
        $products = $categories->map(function($category) 
            return $category->products;
        )->flatten();

        // or use this approach if above not working
        /*$products = collect([]);

        foreach ($categories as $category) 
            $produts = $products->merge($category->products);
        */

        // do your magic
    
    else 
        // not exactly understand what you want to do when $series is not set
    

    // do your magic

【讨论】:

【参考方案4】:

我的方法是在 Serie 模型中创建类似于自定义关系的东西:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Serie extends Model

    public function categories() 
        return $this->belongsToMany('App\Category');
    

    public function products()
    
        return Product::whereIn('id', function($query)
            $query->select('product_id')
                ->from('category_product as cp')
                ->join('category_serie as cs', 'cs.category_id', '=', 'cp.category_id')
                ->where('cs.serie_id', $this->id)
            ;
        );
    

products() 方法将返回一个 Builder 实例。您可以在控制器中使用它,例如:

$serie = Serie::find($series);
$products = $serie->products()->get();

这将只执行两个查询:

select * from `series` where `series`.`id` = ? limit 1
select * 
from `products` 
where `id` in (
    select `product_id`
    from `category_product` as `cp`
    inner join `category_serie` as `cs`
        on `cs`.`category_id` = `cp`.`category_id`
    where `cs`.`serie_id` = ?
)

这也应该是可能的:

$products = $serie->products()
    ->orderBy('created_at', 'desc')
    ->skip(($page - 1) * $itemsPerPage)
    ->take($itemsPerPage)
    ->get()
;

【讨论】:

以上是关于如何在laravel中获取多对多关系项的主要内容,如果未能解决你的问题,请参考以下文章

如何从 laravel 中的中间表(多对多关系)中获取数据

如何通过 Laravel 中的多对多关系获取模型

在 Laravel 4 中如何查询多对多关系?

如何在多对多关系 Laravel 中检索所有相关模型?

如何在Laravel中的多对多关系中添加“别名”?

如何在 Laravel 中检索链接到多对多关系的模型?