staudenmeir / eloquent-has-many-deep

Laravel Eloquent HasManyThrough relationships with unlimited levels

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Need help with self-references in manytomany -> manytomany

vaniok010 opened this issue · comments

I have 2 models/tables:

products
oems

and I have pivot table "oem_product" with "own" pivot field. Each product has multiple oems, own oem (where own = 1) and analog oems (where own = 0)

oem_id product_id own
1 1 1
2 1 0
3 1 0
1 2 0
2 2 0
3 2 1

in my Product model, here is my belongstomany for analogOems:

public function oems(): BelongsToMany
{
    return $this->belongsToMany(Oem::class)
        ->withPivot(['own'])
        ->using(OemProduct::class);
}
public function analogOems(): BelongsToMany
{
    return $this->oems()->wherePivot('own', false);
}

in my Oem model, here is my belongstomany for ownProducts:

public function products(): BelongsToMany
{
    return $this->belongsToMany(Product::class)
        ->withPivot(['own'])
        ->using(OemProduct::class);
}
public function ownProducts(): BelongsToMany
{
    return $this->products()->wherePivot('own', true);
}

i am trying to create a analogsThroughOems relationship in the product model:

public function analogsThroughOems()
{
    return $this->hasManyDeepFromRelations((new Oem())->setAlias('analogs')->ownProducts(), (new Product())->analogOems());
}

this gives me the following error:

Call to undefined relationship [analogsThroughOems] on model [App\Models\Product].

i would like to get all the analogs products for a products through the pivot table

Product::query()->with('analogsThroughOems')->whereIn('id', [1])->get();

in analogsThroughOems I want to receive products with ids [2] for examle oem_product table

Hi @vaniok010,

this gives me the following error:
Call to undefined relationship [analogsThroughOems] on model [App\Models\Product].

How are you trying to use the analogsThroughOems relationship in this case?

like this
Product::query()->with('analogsThroughOems')->whereIn('id', [1])->get();

My custom relation looks like this

public function analogsThroughOems(): BelongsToMany
{
    $instance = $this->newRelatedInstance(Product::class);

    /** @var Builder $relationQuery */
    $relationQuery = $instance->newQuery();
    $relationQuery->join('oem_product as op1', 'op1.product_id', '=', 'products.id');
    $relationQuery->join('oem_product as op2', 'op2.oem_id', '=', 'op1.oem_id');
    $relationQuery->where('op1.own', '=', 0);
    $relationQuery->where('op2.own', '=', 1);

    return $this
        ->newBelongsToMany(
            $relationQuery,
            $this,
            'products as analogs',
            'products.id',
            'analogs.id',
            $this->getKeyName(),
            'op2.product_id'
        )
        ->select('analogs.*');
}

@staudenmeir I think I did it, thank you

public function analogsThroughOems(): HasManyDeep
{
    return $this->hasManyDeep(
        Product::class,
        ['oem_product as analog_oems', Oem::class, 'oem_product as own_oems'],
        ['analog_oems.product_id', 'id', 'own_oems.oem_id', 'id'],
        ['id', 'analog_oems.oem_id', 'id', 'own_oems.product_id']
    )->where('analog_oems.own', false)->where('own_oems.own', true);
}