'Getting parent parents data in a pivot table in Laravel

What Eloquent model would you use to:

Get all Pages that its Company brand color is red/slug.

Where brand color is a pivot table and stored as an ID on the Company table.

So you have brand_colors id, name, slug, hex Have company where it has brand_color_id And Pages that has just the company ID.

I want to grab all pages whose company brand color is X.

How would you go about it?

This table has the company_id

class WebsitePage extends Model
{
    use HasFactory;

    public function scopeFilter($query, array $filters) {

        // Get all pages with a color that the company has
        $query->when($filters['color'] ?? false, fn($query, $color) =>
        $query->whereHas('color', fn ($query) =>
                $query->where('name', $color)
            )
        );

    }

    // Where URL slug 'red' color, associated with company brand_color_id matches brandColor slug
    // or just simpley call $company->color() ?
    public function color()
    {
        // return $this->with(Company::class, 'brand_color_id');
        // return $this->belongsTo(Company::class, 'company_id');
        // dd($this->with())

        // return Company::with('color.red');
    }

This table has brand_color_id, etc.

class Company extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'name',
        'slug',
        'description'
    ];


    public function pages() {
        return $this->hasMany(WebsitePage::class);
    }

    public function color() {
        return $this->belongsTo(BrandColor::class, 'brand_color_id');
    }
}

This table has: id | name | slug | hex

class BrandColor extends Model
{
    use HasFactory;
}

So knowing this, how would you get all pages whose company color is the one filtered?

In terms of the page controller, this is what I'm doing:

class PageController extends Controller
{
    public function index(WebsitePage $websitePage)
    {
        // return view('web.inspiration.pages.index', [
        //     'pages' => WebsitePage::latest()->paginate(30)
        // ]);
        return view('web.inspiration.pages.index', [
            'pages' => WebsitePage::latest()->filter(
                request(['color'])
            )->paginate(30)->withQueryString()
        ]);
    }
}


Solution 1:[1]

Your model layout isn't described that well, but I think you just want to define a HasOneThrough relationship to join WebsitePage to BrandColor:

class WebsitePage extends Model
{
    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class);
    }

    public function color(): HasOneThrough
    {
        return $this->hasOneThrough(BrandColor::class, Company::class);
    }
}

class Company extends Model
{
    public function color(): BelongsTo
    {
        return $this->belongsTo(BrandColor::class);
    }
}

class BrandColor extends Model
{
    public function company(): HasOne
    {
        return $this->hasOne(Company::class);
    }
}

Then in your controller, just use a condition on your whereHas() and with() calls:

class PageController extends Controller
{
    public function index(): View
    {
        $color = request("color");
        $pages = WebsitePage
            ::whereHas("color", fn ($q) => $q->where("color", $color))
            ->with(["color" => fn ($q) => $q->where("color", $color)])
            ->paginate(30)
            ->withQueryString();
        return view("web.inspiration.pages.index", compact($pages));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 miken32