Reputation: 35
I've created 4 database tables:
Tool
ID | NAME | TOOLTYPE_ID
Tooltype
ID | NAME
Toolcategory
ID | NAME
Tool_Toolcategory
TOOL_ID | TOOLCATEGORY_ID
The models are as following:
class Tool extends Eloquent {
public function toolCategories()
{
return $this->belongsToMany('ToolCategory', 'tool_toolcategory', 'tool_id', 'toolcategory_id');
}
public function tooltype()
{
return $this->belongsTo('ToolType');
}
}
class ToolType extends Eloquent {
public function tools()
{
return $this->hasMany('Tool', 'tooltype_id');
}
}
class ToolCategory extends Eloquent {
public function tools()
{
return $this->belongsToMany('Tool', 'tool_toolcategory', 'tool_id', 'toolcategory_id');
}
}
Ok, my problem is getting toolcategories based on created tools with a specific tooltype.
Example I want all the categories related to the tools that has the type "Software".
I am kinda lost, i have looked at trying to use scope in my toolcategory model, doing something like this:
public function scopeHasType($query, $type)
{
return $query->whereHas('tools.tooltype', function($q) use ($type)
{
$q->where('name', '=', $type);
})->exists();
}
which didn't really work :) then i tried this
$categories = ToolCategory::whereHas('tools.tooltype', function($query)
{
$query->where('tooltype_id', '=', 'Software');
})->get();
again no luck. So i was hoping that this makes sense to someone, and they could push me in the right direction. Thank you in advance.
Upvotes: 1
Views: 444
Reputation: 81157
Eloquent naming convention says:
StudlyCased
& singularcamelCased
(relation dynamic properties need this)snake_cased
& pluralsnake_cased
model1_model2
snake_cased singular (in alphabetical order)That being said, Eloquent for a model ToolCategory
looks for the table tool_categories
.
So you need to specify table names whenever are not convention compliant (singular, not snake cased and so on):
// for example Tool model
protected $table = 'tool';
Also you need foreign keys to be passed to the relationship definition in order to let Eloquent know what to look for. However that you already did:
// ToolType model
public function tools()
{
// here Eloquent would look for tool_type_id (based on related model)
return $this->hasMany('Tool', 'tooltype_id');
}
// Tool model
public function tooltype()
{
// here Eloquent looks for tooltype_id by default (based on relation name)
return $this->belongsTo('ToolType');
}
Now, your relations are OK with 1 exception (keys wrong order):
class ToolCategory extends Eloquent {
public function tools()
{
return $this->belongsToMany('Tool', 'tool_toolcategory', 'toolcategory_id', 'tool_id');
}
Finally, whereHas
doesn't work on nested relation (yet, check this: https://github.com/laravel/framework/pull/4954), so at the moment you need this:
// ToolCategory model
public function scopeHasType($query, $type)
{
return $query->whereHas('tools', function ($q) use ($type) {
$q->whereHas('tooltype', function($q) use ($type) {
// use table prefix, since this is going to be join
$q->where('tooltype.name', '=', $type);
});
});
}
Upvotes: 2