Select 根据 Laravel 中的类型变形关系中的特定列
Select specific column from morph relation according to type in Laravel
我正在尝试编写一个查询,其中 select 来自模型的列,然后 select 来自变形关系 table 的一些列。但我不知道 select 列,并且关系 table 有不同的列。所以有些列没有 slug,有些有。
public function index()
{
$menus = Menu::whereActive(true)
->with([
'menuable' => function ($q) {
// This gives error if there is no relation Pages model
$q->whereActive(true)->select('pages.id', 'pages.slug');
// Below not working
// if($q->type === Page::class){
// $q->whereActive(true)->select('pages.id', 'pages.slug');
// } else if($q->type === Category::class){
// $q->whereActive(true)->select('categories.id',
'categories.slug');
// }
}
])
->get(['id', 'menuable_id', 'menuable_type', 'name']);
$response = [
'menus' => $menus,
];
return $this->sendResponse($response);
}
型号
class Menu extends Model
{
public function menuable()
{
return $this->morphTo();
}
}
class Page extends Model
{
public function menu()
{
return $this->morphOne(Menu::class, 'menuable');
}
}
class Category extends Model
{
public function menu()
{
return $this->morphOne(Menu::class, 'menuable');
}
}
如何 select 变形关系中的特定列检查变形类型?我正在使用 Laravel 版本 8.
多态关系是 Eloquent 知道的,而 DBMS 尚未在其中实现此功能。
所以不能一个sql查询将一个table连接到另一个tables基于变形列。
因此您必须对模型中的每个多态连接关系使用不同的查询:
//you can retrieve distinct menu based on their relation
Menu::whereActive(true)->hasPage()->with('pages');
//and having the ralations in the menu model:
public function posts
Menu::whereActive(true)->hasCategory();
//scope in menu class can be like:
public function scopePage($query){
return $query->where('menuable_type',Page::class);
}
public function scopeCategory($query){
return $query->where('menuable_type',Category::class);
}
//with these you can eager load the models
Menu::whereActive(true)->hasPage()->with('page');
Menu::whereActive(true)->hasCategory()->with('category');
public function page(){
return $this->belongsTo(Page::class);
}
public functioncategory(){
return $this->belongsTo(Category::class);
}
如果您希望通用接口动态使用其中之一。
你可以使用:
$menu->menuable->id
$menu->menuable->slug
我不确定你想回复哪些栏目,但我可以从你的问题中猜到,我想你想要两个模型的 id
和 slug
。
public function index(){
$pagedMenu = Menu::whereActive(true)->hasPage()->with('page');
$categoriedMenu = Menu::whereActive(true)->hasCategory()->with('category');
$menues = $pagedMenu->merge($categoriedMenu);
$response = [
'menus' => $menus,
];
return $this->sendResponse($response);
}
您可以根据 morph-class 执行单独的过滤器。这可以通过 whereHasMorph
(https://laravel.com/docs/8.x/eloquent-relationships#querying-morph-to-relationships).
来实现
如果您需要自动解析关系,您可以使用 with
。这会自动将可变形对象预加载到您生成的集合中。
以下示例使用 orWhere
每个可变形对象有 2 个单独的查询。
$menus = Menu::whereActive(true)
->whereHasMorph('menuable', [Page::class], function (Builder $query) {
// perform any query based on page-related entries
})
->orWhereHasMorph('menuable', [Category::class], function (Builder $query) {
// perform any query based on category-related entries
})
->with('menuable')
;
另一种方法是将两个 class 都传递给第二个参数。在那种情况下,您可以检查闭包中的类型。
$menus = Menu::whereActive(true)
->whereHasMorph('menuable', [Page::class, Category::class], function (Builder $query, $type) {
// perform any query independently of the morph-target
// $q->where...
if ($type === (new Page)->getMorphClass()) {
// perform any query based on category-related entries
}
if ($type === (new Category)->getMorphClass()) {
// perform any query based on category-related entries
}
})
->with('menuable')
如果需要,您还可以预加载嵌套关系。 (https://laravel.com/docs/8.x/eloquent-relationships#nested-eager-loading-morphto-relationships)
$menus = Menu::whereActive(true)
->with(['menuable' => function (MorphTo $morphTo) {
$morphTo->morphWith([
Page::class => ['calendar'],
Category::class => ['tags'],
]);
}])
我正在尝试编写一个查询,其中 select 来自模型的列,然后 select 来自变形关系 table 的一些列。但我不知道 select 列,并且关系 table 有不同的列。所以有些列没有 slug,有些有。
public function index()
{
$menus = Menu::whereActive(true)
->with([
'menuable' => function ($q) {
// This gives error if there is no relation Pages model
$q->whereActive(true)->select('pages.id', 'pages.slug');
// Below not working
// if($q->type === Page::class){
// $q->whereActive(true)->select('pages.id', 'pages.slug');
// } else if($q->type === Category::class){
// $q->whereActive(true)->select('categories.id',
'categories.slug');
// }
}
])
->get(['id', 'menuable_id', 'menuable_type', 'name']);
$response = [
'menus' => $menus,
];
return $this->sendResponse($response);
}
型号
class Menu extends Model
{
public function menuable()
{
return $this->morphTo();
}
}
class Page extends Model
{
public function menu()
{
return $this->morphOne(Menu::class, 'menuable');
}
}
class Category extends Model
{
public function menu()
{
return $this->morphOne(Menu::class, 'menuable');
}
}
如何 select 变形关系中的特定列检查变形类型?我正在使用 Laravel 版本 8.
多态关系是 Eloquent 知道的,而 DBMS 尚未在其中实现此功能。 所以不能一个sql查询将一个table连接到另一个tables基于变形列。
因此您必须对模型中的每个多态连接关系使用不同的查询:
//you can retrieve distinct menu based on their relation
Menu::whereActive(true)->hasPage()->with('pages');
//and having the ralations in the menu model:
public function posts
Menu::whereActive(true)->hasCategory();
//scope in menu class can be like:
public function scopePage($query){
return $query->where('menuable_type',Page::class);
}
public function scopeCategory($query){
return $query->where('menuable_type',Category::class);
}
//with these you can eager load the models
Menu::whereActive(true)->hasPage()->with('page');
Menu::whereActive(true)->hasCategory()->with('category');
public function page(){
return $this->belongsTo(Page::class);
}
public functioncategory(){
return $this->belongsTo(Category::class);
}
如果您希望通用接口动态使用其中之一。 你可以使用:
$menu->menuable->id
$menu->menuable->slug
我不确定你想回复哪些栏目,但我可以从你的问题中猜到,我想你想要两个模型的 id
和 slug
。
public function index(){
$pagedMenu = Menu::whereActive(true)->hasPage()->with('page');
$categoriedMenu = Menu::whereActive(true)->hasCategory()->with('category');
$menues = $pagedMenu->merge($categoriedMenu);
$response = [
'menus' => $menus,
];
return $this->sendResponse($response);
}
您可以根据 morph-class 执行单独的过滤器。这可以通过 whereHasMorph
(https://laravel.com/docs/8.x/eloquent-relationships#querying-morph-to-relationships).
如果您需要自动解析关系,您可以使用 with
。这会自动将可变形对象预加载到您生成的集合中。
以下示例使用 orWhere
每个可变形对象有 2 个单独的查询。
$menus = Menu::whereActive(true)
->whereHasMorph('menuable', [Page::class], function (Builder $query) {
// perform any query based on page-related entries
})
->orWhereHasMorph('menuable', [Category::class], function (Builder $query) {
// perform any query based on category-related entries
})
->with('menuable')
;
另一种方法是将两个 class 都传递给第二个参数。在那种情况下,您可以检查闭包中的类型。
$menus = Menu::whereActive(true)
->whereHasMorph('menuable', [Page::class, Category::class], function (Builder $query, $type) {
// perform any query independently of the morph-target
// $q->where...
if ($type === (new Page)->getMorphClass()) {
// perform any query based on category-related entries
}
if ($type === (new Category)->getMorphClass()) {
// perform any query based on category-related entries
}
})
->with('menuable')
如果需要,您还可以预加载嵌套关系。 (https://laravel.com/docs/8.x/eloquent-relationships#nested-eager-loading-morphto-relationships)
$menus = Menu::whereActive(true)
->with(['menuable' => function (MorphTo $morphTo) {
$morphTo->morphWith([
Page::class => ['calendar'],
Category::class => ['tags'],
]);
}])