Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have a HasManyThrough relationship that's deeper than two levels?

I have the following models:

Product
BaseProduct
BaseCode
Series

Each of them is something of a separate entity, but they're related.

Product has a foreign key to BaseProduct, BaseProduct has a foreign key to BaseCode and BaseCode has a foreign key to Series.

I have specified a method within my BaseCode model so I can select all of the Products that are related to that particular BaseCode:

public function Products()
{
    return $this->hasManyThrough('Product', 'BaseProduct', 'BaseCodeId', 'BaseProductId');
}

BaseCodeId is the PK for the BaseCode and the FK in BaseProduct that is pointing to that PK, and BaseProductId is the PK for BaseProduct, and in the Product table, there's a FK that points to it.

This is all well and good, and works just dandy for me.

I'd like to go one level further though, and define something like the following in my Series model:

public function Products()
{
    //It's here that I'd have no idea what to do - is there something like a three-level deep "hasManyThroughThrough" or something?
    return $this->BaseProducts()-> /* and then whatever I'd do here to get the products */
}

public function BaseProducts()
{
    return $this->hasManyThrough('BaseProduct', 'BaseCode', 'SeriesId', 'BaseCodeId');
}

How do I get all of the Products associated with Series like that?

like image 752
Nathan Lutterman Avatar asked Mar 20 '23 16:03

Nathan Lutterman


2 Answers

I am somewhat new to 4.1, but it looks as though hasManyThrough() was not designed for the types of relationships you are looking for and is really just a shortcut for two level deep eager loading.

Try traditional eager loading instead...

$data = Product::with('BaseProduct.BaseCode.Series');

You will need to make sure the relationships are setup in your models as necessary and instead of calling model names, you will want to call the methods that are defining the relationships.

Also obviously, be sure your models know what the primary keys are by using protected $primaryKey = 'SeriesID' etc...

like image 183
user1669496 Avatar answered Apr 06 '23 00:04

user1669496


I created a HasManyThrough relationship with unlimited levels: Repository on GitHub

After the installation, you can use it like this:

class Series extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function products() {
        return $this->hasManyDeep(Product::class,
            [BaseCode::class, BaseProduct::class],
            ['SeriesId', 'BaseCodeId', 'BaseProductId']
        );
    }
}
like image 24
Jonas Staudenmeir Avatar answered Apr 06 '23 00:04

Jonas Staudenmeir