D. Petrov
D. Petrov

Reputation: 1167

Access a property of an object as key in where clause in laravel

I'll start directly off with my example. The thing is, I have a couple of hasMany and belongsTo relationships and I'd like to access a property of one of the returned object as a key in a where clause. Let's say I have a model named Price and it has three belongsTo connections to three models named profileSystem, profileType and colorGroup. Each of my three other models have a hasMany connection to the Price model. So if I have an instance of my profileType model, I'd like to call it's price where accordingly the profileSystem and the colorGroup parents will have some certain values. Example that works:

App\ProfileType::find(1) 
                -> prices -> where('profileType', App\ProfileType::find(1))
                -> where('colorGroup', App\ColorGroup::find(1))
                -> first()->value;

As you can see, the comparison here works directly with the whole instances of the colorGroup and profileType models that belong with the Price model. What I'd like to do is no to compare the whole models, but only a single property, like so:

->where('colorGroup->id', 1)

or

->where('colorGroup->id', App\ColorGroup::find(1) -> id)

The question is all syntax that I'm not common with in laravel. I also couldn't find anything in the documentation. Thanks in advance!

Upvotes: 0

Views: 726

Answers (3)

D. Petrov
D. Petrov

Reputation: 1167

You see, what I actually needed appeared to be the whereHas function! So instead of my thought up suggestion like ->where('colorGroup->id', 1) the solution looks like

->whereHas('colorGroup', function($q){ 
    $q->where('id', 1);
})->get();

Upvotes: 0

Alex
Alex

Reputation: 1418

If your price belongs to a colourGroup, it means that you have some kind of foreign key in your prices table "eg colour_group_id". Therefore, you should just do something like

->where('colour_group_id', $acolourgroup->id)

If it understood it right, you will get what you want


EDIT :

You can access to a relationship foreign key with $instance->relation()->getForeignKey();

So what I would to is make a scope like that :

public function scopeWhereRelationship($query, $r){
    return $query->where($this->relationship()->getForeignKey(), $r->id);
}

But I'm not really sure that it is what you want


EDIT 2 :

You can easily generalize the scope I gave you. For example, you can add the scope to your root model (a class that every model will extend) and add the name of the relationship as a parameter. For example :

public function scopeWhereBelongsTo($query, $relationship, $instance)
{
    $relationship = $this->{$relationship}();
    return $query->where($relationship->getForeignKey(), $instance->getAttribute($relationship->getOwnerKey()));
}

Now, you have on every model a scope that you can call like this :

Model::whereBelongsTo('thenameofyourrelationship', $theinstance);

A little bit of an explanation :

$this->{$relationship}()

This gets the relationship, aka the BelongsTo class representing the relationship.

With $relationship->getForeignKey() you then get the name of the foreign key.

With $relationship->getOwnerKey() you get the name of the owner key, that is the field that is used in the second table (the one the model belongs to).

With $instance->getAttribute($relationship->getOwnerKey()) you then get the value of the owner key.

Upvotes: 0

Alex Harris
Alex Harris

Reputation: 6402

You can use scopes for each of these:

class ColorGroup {

    public function scopeColor($query, $color)
    {
        return $query->where('id', $color);
    }

}

Upvotes: 1

Related Questions