Laravel 按相关表排序
Posted
技术标签:
【中文标题】Laravel 按相关表排序【英文标题】:Laravel order by related table 【发布时间】:2016-08-19 19:24:50 【问题描述】:我的项目中有产品和类别模型。产品属于类别。由于 Product 有外键 category_id,我可以像这样轻松地对输出进行排序:
$products = Product::orderBy('category_id', 'asc')->get();
但我真正想要的是按类别名称对产品进行排序,所以我尝试了:
$products = Product::with(['categories' => function($q)
$q->orderBy('name', 'asc')->first();
]);
但这什么也没输出。作为测试,我返回了return Product::with('categories')->first();
,它的输出很好......
这里是 Eloquent 关系。
产品
class Product extends Model
protected $fillable = [
'name',
'description',
'price',
'category_id',
];
protected $hidden = [
'created_at',
'updated_at',
];
public function categories()
return $this->belongsTo('\App\Category', 'category_id');
类别:
class Category extends Model
protected $fillable = [
'name'
];
public function products()
return $this->hasMany('\App\Product');
还有视图部分:
@foreach ($products as $product)
<tr>
<td>!! $product->categories->name !!</td>
<td>
@if(!empty($product->picture))
Yes
@else
No
@endif
</td>
<td>!! $product->name !!</td>
<td>!! $product->description !!</td>
<td>!! $product->price !!</td>
<td>
<a href=" url('/product/'.$product->id.'/edit') ">
<i class="fa fa-fw fa-pencil text-warning"></i>
</a>
<a href="" data-href="route('product.destroyMe', $product->id)"
data-toggle="modal" data-target="#confirm-delete">
<i class="fa fa-fw fa-times text-danger"></i>
</a>
</td>
</tr>
@endforeach
【问题讨论】:
【参考方案1】:我没有对此进行测试,但我认为这应该可以工作
// Get all the products
$products = \App\Product::all();
// Add Closure function to the sortBy method, to sort by the name of the category
$products->sortBy(function($product)
return $product->categories()->name;
);
这也应该有效:
$products = Product::with('categories')->get()
->sortBy(function($product)
return $product->categories->name;
)
【讨论】:
那行不通。而且没有逻辑意义。产品只能有一个类别。我已经测试了我在 Tinker 中的关系,它们可以正常工作。模型不应该是问题 这是语法问题,如果产品只有一个类别,请不要将其命名为复数形式。令人困惑 我以为这是约定俗成的事情? 它不应该影响结果,但它只是违反了我认为一对多关系的约定 更新了答案【参考方案2】:你可以使用join(),试试下面的代码
$query = new Product; //new object
//$query = Product::where('id','!=',0);
$query = $query->join('categories', 'categories.id','=','products.categories.id');
$query = $query->select('categories.name as cat_name','products.*');
$query = $query->orderBy('cat_name','asc');
$record = $query->get();
【讨论】:
为什么是新产品?我需要所有现有产品 使用new你可以创建'Product'类的新对象所以如果你可以附加一些额外的where子句,你也可以用第二行替换第一行。 如果有不属于任何类别的产品,请使用leftjoin
而不是join
。【参考方案3】:
您可以简单地向 Eloquent 急切加载提供函数,您可以在其中处理相关表的查询方式。
$product = Product::with(['categories' => function ($q)
$q->orderBy('name', 'asc');
])->find($productId);
【讨论】:
【参考方案4】:在 laravel 中,如果不手动加入相关表,就无法按相关表执行订单,这真的很尴尬,但是这个 can package 可以为你做到这一点https://github.com/fico7489/laravel-eloquent-join
【讨论】:
以上是关于Laravel 按相关表排序的主要内容,如果未能解决你的问题,请参考以下文章
列表模型如何按 DOWN-VOTES 的数量排序到相关模型 - laravel,雄辩