Home > other >  Laravel - hasOne relation based on model attribute
Laravel - hasOne relation based on model attribute

Time:09-30

I have a problem, I need to make a relation based on an attribute from the model$this->type, my code is as follows:

class Parent extends Model {

    protected $attributes = [
        'type' => self::TYPE_A 
    ];

    public function child()
    {
        return match ($this->type) {
            self::TYPE_A => $this->hasOne(Cousin::class)->where('type', Cousin::TYPE_A),
            self::TYPE_B => $this->hasOne(Cousin::class)->where('type', Cousin::TYPE_B),
            self::TYPE_C,
            self::TYPE_D => $this->hasOne(Cousin::class)->where('type', Cousin::TYPE_C),
            self::TYPE_E,
            self::TYPE_F => $this->hasOne(Cousin::class)->where('type', Cousin::TYPE_D)
        };
    }

    public function children()
    {
        return $this->hasMany(Cousin::class);
    }

}

If I do this inside artisan tinker, I get the child relation correctly:

$parent = Parent::first();

$parent->child;

However if my queues execute the code the child relation is returned as null.

If I put logger($this) in the first line of the relation I get an empty model when inside queues:

[2021-09-29 23:51:59] local.DEBUG: {"type":1}

Any idea on how to solve this?

CodePudding user response:

Apparently it is not possible to use the relationship in this way.

The relationship I want uses composite keys and Eloquent doesn't support it.

They created a package to enable this to happen: https://github.com/topclaudy/compoships

But I don't want to add any more packages to my application as it is already too big.

My solution was to add one more column in the cousins table to know which one to use:

public function child() {
    return $this->hasOne(Cousin::class)
        ->where('main', true);
}

CodePudding user response:

protected $attributes = [
    'type'
];

public function getTypeAttribute() {
        return $this->hasOne(Cousin::class)
            ->where('main', true);
}

Then call it anywhere

$parent->type

Or you can do it as follow

public function typeMainTrue() {
        return $this->hasOne(Cousin::class)
            ->where('main', true);
}

Then call it anywhere

$parent->typeMainTrue
  • Related