如何在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中获取多对多关系项的主要内容,如果未能解决你的问题,请参考以下文章