如果子关系在 Laravel 中有结果,我如何只返回父级,如果关系是三重嵌套的?

Posted

技术标签:

【中文标题】如果子关系在 Laravel 中有结果,我如何只返回父级,如果关系是三重嵌套的?【英文标题】:How do I only return the parent if child has results in Laravel, if the relations are triple nested? 【发布时间】:2021-05-13 07:47:35 【问题描述】:

我有以下关系Client > belongsToMany Brand > hasMany Handles > hasMany Content.

如果Content 有行,我将如何只返回Handles,如果Handles 有行,则只返回Brands,如果它也有行,则只返回Client,我从PostgreSQL 数据库中获取?

这是模型的刮版

客户端模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Client extends Model

    use HasFactory;
    use SoftDeletes;

    protected $hidden = ['pivot'];

    protected $fillable = ['title', 'subscription_expire', 'subscription_level'];


    /**
     * Get brands for client
     *
     * @return BelongsToMany
     */
    public function brands(): BelongsToMany
    
        return $this->belongsToMany(
            Brand::class,
            'organized_objects',
            'client_id',
            'object_id'
        )->wherePivot('object_type', 'brand');
    

品牌模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Brand extends Model

    use HasFactory;
    use SoftDeletes;

    /**
     * Get handles for brand
     *
     * @return BelongsToMany
     */
    public function handles(): BelongsToMany
    
        return $this->belongsToMany(Handle::class, 'handle_pivots', 'handle_pivot_id', 'handle_id');
    

手柄模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Handle extends Model

    use HasFactory;

    protected $fillable = ['name', 'platform'];

    /**
     * Get content of handle.
     *
     * @return HasMany
     */
    public function content(): HasMany
    
        return $this->hasMany(PureContent::class, 'handle_id');
    


目前,我在控制器中执行以下操作以获取句柄所需的内容。

/**
 * Client metrics
 *
 * Displays metrics for the given client
 *
 * @param Request $request
 * @param Client  $client
 *
 * @return JsonResponse
 */
public function index(Request $request, Client $client): JsonResponse

    $to = $request->get('to');
    $from = $request->get('from');
    $to_date = $to ? Carbon::parse($to) : Carbon::now();
    $from_date = $from ? Carbon::parse($from) : $to_date->copy()->startOfYear();

    $client_content = $client->with([
        'brands' => function ($q) use ($to_date, $from_date) 
            $q->with([
                'handles' => function ($q) use ($to_date, $from_date) 
                    $q->whereHas('content', function ($q) use ($to_date, $from_date) 
                        $q->whereBetween('created_at', [$from_date, $to_date]);
                    )->with(['content' => function ($q) use ($to_date, $from_date) 
                        $q->whereBetween('created_at', [$from_date, $to_date]);
                    ])->get();
                ,
            ])->get();
        ,
    ])->get();

    return response()->json($client_content);

但是当我返回集合时,我仍然得到相关的集合只是空的。

例如,在查询中添加一个 Collection 模型需要多少费用?它与品牌 > 处理 > 内容的设置相同?

【问题讨论】:

不应该更像$client-&gt;with(['brands'])-&gt;whereHas('handles', function ($query) $query-&gt;whereBetween.... @C4pt4inC4nn4bis 不,只是查询Client::handles(); 也许这有帮助webdevetc.com/programming-tricks/laravel/laravel-eloquent/… 【参考方案1】:

我相信您的主查询中还需要嵌套 whereHas 子句来过滤不相关的客户记录

$client_content=$client->with(.....)
                       ->whereHas('brands', function (Builder $query) use ($to_date, $from_date) 
                            $query->whereHas('handles', function (Builder $query) use ($to_date, $from_date) 
                                $query->whereHas('content', function (Builder $query) use ($to_date, $from_date) 
                                    $query->whereBetween('created_at', [$from_date, $to_date]);
                                );
                            );
                        )->get();

现在您只是从 with() 部分过滤关联的记录,但您还需要在主查询中使用此过滤器来删除具有空集合的此类记录

【讨论】:

以上是关于如果子关系在 Laravel 中有结果,我如何只返回父级,如果关系是三重嵌套的?的主要内容,如果未能解决你的问题,请参考以下文章

如果子字符串包含在引用字符串中,如何使用布尔表达式进行匹配?

如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?

如果子查询的结果为 NULL,MySQL 整个查询将失败

Laravel 8 多表关系

Laravel 5:用户关注其他用户(如twitter) - 如何设置关系

如何从 Laravel 中的 hasMany() 关系中获取所有结果?