查询 Laravel 嵌套关系 [Laravel 6.x]
Query Laravel nested relationship [Laravel 6.x]
我的 Laravel 应用程序中有一个页面,我在其中获取类别和该类别中的预加载事件。它工作正常。我现在想做的是获取类别,但这次,根据用户选择的 region/location 获取事件。这些是我正在使用的模型;
1.Region Class
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Region extends Model
{
/**
* Get events within region
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function events()
{
return $this->hasMany(Event::class);
}
}
类别Class
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'category_name', 'description', 'type', 'slug'
];
/**
* Get all events that belong to a category
*
* @return Illuminate\Database\Eloquent\Relations\HasMany
*/
public function events()
{
return $this->hasMany(Event::class)->where('start_date', '>=', today())->orderBy('start_date', 'asc');
}
}
3.Event
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
/**
* Get an event's category
*
* @return Illuminate\Database\Eloquent\Relations\BelongsTo;
*/
public function category()
{
return $this->belongsTo(Category::class);
}
/**
* Get region of event
*
* @return [type] [description]
*/
public function region()
{
return $this->belongsTo(Region::class);
}
}
这是 returns 事件分类的查询;
if (session()->has('region')) {
$region_name = session()->get('region');
$region = Region::where('region_name', $region_name)->firstOrFail();
$categories = Category::withCount('events')
->with('events')
->whereHas('events', function (Builder $query) use ($region) {
$query->where('region_id', $region->id);
})
->orderBy('events_count', 'desc')
->take(5)
->get();
}
摘要:我想获取用户所选位置的前 5 个类别的事件。
在此先感谢您的帮助。
你看过hasManyThrough
关系吗?
https://laravel.com/docs/5.8/eloquent-relationships#has-many-through
如果你给你的 Region
模型很多 Categories
通过 Event
class:
public function categories()
{
return $this->hasManyThrough('App\Category', 'App\Event');
}
您应该可以拨打电话:
$region->categories;
哪个应该 return 具有该地区事件的所有类别。然后您可以预先加载每个类别中的事件,按事件数量排序并在输出到您的视图之前获取前 5 个。
备选
另一种方法是简单地获取 region_id 是所选区域的所有事件,并为类别添加 groupBy
:
$eventsByCategory = Event::where('region_id', $selectedRegion)->groupBy('category_id);
然后,一旦您按类别对事件进行了分组,您就可以按计数排序并获得前 5 名。
$eventsByCategory->sort()->take(5);
旁注:
我会小心处理类别模型上的事件关系。我认为将 where
添加到 returned 值将 return Builder
而不是 Relation
的实例,这意味着您可能无法利用某些关系的功能。
我建议您查看 Event
模型上的范围,而不是您可以根据您希望获取过去事件的频率在全局或本地应用。
对类别查询试试这个:
$categories = Category::with(['events' => function ($query) use ($region) {
$query->where('region_id', $region->id);
}])->take(5)->get();
我的 Laravel 应用程序中有一个页面,我在其中获取类别和该类别中的预加载事件。它工作正常。我现在想做的是获取类别,但这次,根据用户选择的 region/location 获取事件。这些是我正在使用的模型;
1.Region Class
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Region extends Model
{
/**
* Get events within region
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function events()
{
return $this->hasMany(Event::class);
}
}
类别Class
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'category_name', 'description', 'type', 'slug' ]; /** * Get all events that belong to a category * * @return Illuminate\Database\Eloquent\Relations\HasMany */ public function events() { return $this->hasMany(Event::class)->where('start_date', '>=', today())->orderBy('start_date', 'asc'); } }
3.Event
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
/**
* Get an event's category
*
* @return Illuminate\Database\Eloquent\Relations\BelongsTo;
*/
public function category()
{
return $this->belongsTo(Category::class);
}
/**
* Get region of event
*
* @return [type] [description]
*/
public function region()
{
return $this->belongsTo(Region::class);
}
}
这是 returns 事件分类的查询;
if (session()->has('region')) {
$region_name = session()->get('region');
$region = Region::where('region_name', $region_name)->firstOrFail();
$categories = Category::withCount('events')
->with('events')
->whereHas('events', function (Builder $query) use ($region) {
$query->where('region_id', $region->id);
})
->orderBy('events_count', 'desc')
->take(5)
->get();
}
摘要:我想获取用户所选位置的前 5 个类别的事件。
在此先感谢您的帮助。
你看过hasManyThrough
关系吗?
https://laravel.com/docs/5.8/eloquent-relationships#has-many-through
如果你给你的 Region
模型很多 Categories
通过 Event
class:
public function categories()
{
return $this->hasManyThrough('App\Category', 'App\Event');
}
您应该可以拨打电话:
$region->categories;
哪个应该 return 具有该地区事件的所有类别。然后您可以预先加载每个类别中的事件,按事件数量排序并在输出到您的视图之前获取前 5 个。
备选
另一种方法是简单地获取 region_id 是所选区域的所有事件,并为类别添加 groupBy
:
$eventsByCategory = Event::where('region_id', $selectedRegion)->groupBy('category_id);
然后,一旦您按类别对事件进行了分组,您就可以按计数排序并获得前 5 名。
$eventsByCategory->sort()->take(5);
旁注:
我会小心处理类别模型上的事件关系。我认为将 where
添加到 returned 值将 return Builder
而不是 Relation
的实例,这意味着您可能无法利用某些关系的功能。
我建议您查看 Event
模型上的范围,而不是您可以根据您希望获取过去事件的频率在全局或本地应用。
对类别查询试试这个:
$categories = Category::with(['events' => function ($query) use ($region) {
$query->where('region_id', $region->id);
}])->take(5)->get();