Reputation: 1167
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
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
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
Reputation: 6402
You can use scopes for each of these:
class ColorGroup {
public function scopeColor($query, $color)
{
return $query->where('id', $color);
}
}
Upvotes: 1