Make sure you have set all relations in the models, then:
$posts = App\Post::whereHas('collected_item', function($query) use ($q) {
$query->whereHas('item_model', function($query) use ($q) {
$query->where('model_name', 'like', $q . '%');
});
});
Not sure though, never go deeper then 1 level when it comes to querying relationships.
It works, but this is done without using the hasManyThrough method defined in Item_model, as per laravel docs retrieving posts with the hasManyThrough method should be a matter of $item->post which doesn't work. I could delete the hasManyThrough stuff from the Item_model completely and that would work anyway. So this is not the solution.
If I read it correctly on laravel.com docs, your second code snippet actually does what it should. It will retrieve the item_model with the posts attached.
$item->posts should give you a collection with posts.
If you only want the posts, you need to start with the Post model or use collection methods and get them the hard way.
PS: you tell me my code works, but why does it have to be with the hasManyThrough relation?
Well it doesn't. If I do
$models_with_posts = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->with('posts')->get();
I get the model with the posts, then I do
$posts = $models_with_posts->posts;
result:
Undefined property: Illuminate\Database\Eloquent\Collection::$posts
Even if your code works what I'm trying to understand is why in heaven the hasManyThrough method, which should easily retrieve all the posts for a model, it not working at all.
Damn it, now you made me curious :p
How is the relation between item_model and collected_item defined? I don't see a item_model_id in your collected_item model.
I believe you need to add 1 more parameter to your hasManyThrough method
$this->hasManyThrough('App\Post', 'App\Collected_item', 'model_id', 'collected_item_id', 'id');
Actually hasManythrough only accepts 4 arguments: "The first argument passed to the hasManyThrough method is the name of the final model we wish to access, while the second argument is the name of the intermediate model. The third argument is the name of the foreign key on the intermediate model, while the fourth argument is the name of the foreign key on the final model."
here's the relations you asked:
class collected_item extends Model
{
public function Item_model(){
return $this->hasOne('App\Item_model', 'id', 'model_id');
}
}
class Item_model extends Model
{
public function collected_item(){
return $this->belongsToMany('App\Collected_item');
}
}
I believe your relations are wrong for what you are trying to achieve.
It should be:
A belongsToMany (many-to-many) relation like you have in your item_model model, you need an intermediate table to store the relationship between item_model and collected_item.
even adding 'id' as 5th argument doesn't change anything. Same error.
LaurentMeganck said:
I believe your relations are wrong for what you are trying to achieve.
It should be:
Item_model hasMany collected_item collected_item belongsTo item_model collected_item hasMany posts posts belongsTo collected_item
A belongsToMany (many-to-many) relation like you have in your item_model model, you need an intermediate table to store the relationship between item_model and collected_item.
... hm I don't know. My "collected_item" is unique as it has other relations regarding item_model characteristics, so for example a collected guitar hasOne Guitar_Item not Many, only one.
and I forgot to add the relationship between collected_item and posts that is like this:
class collected_item extends Model
{
public function post(){
return $this->belongsToMany('App\Post');
}
}
because there can be MANY posts regarding the same collected item
and
class Post extends Model
{
public function collected_item(){
return $this->belongsTo('App\Collected_item')->with('Item_model','Designer', 'Some_Stuff');
}
}
because a post belongsTo one and only one Collected_item
it's the item model that belongsToMany Collected_item
Hi, chriz74x ofcourse Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and \Illuminate\Database\Eloquent\Collections
u can use relations only on instances of Illuminate\Database\Eloquent\Model
.
jasonrust said:
Hi, chriz74x ofcourse
Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and\Illuminate\Database\Eloquent\Collections
u can use relations only on instances ofIlluminate\Database\Eloquent\Model
So what is the solution to retrieve the posts? What is the syntax?
LaurentMeganck said:
I believe your relations are wrong for what you are trying to achieve.
It should be:
- Item_model hasMany collected_item
- collected_item belongsTo item_model
- collected_item hasMany posts
- posts belongsTo collected_item
A belongsToMany (many-to-many) relation like you have in your item_model model, you need an intermediate table to store the relationship between item_model and collected_item.
I tried to modify the relationships as you suggested, it broke everything and the hasManyThrough method still doesn't work
chriz74x said:
jasonrust said:
Hi, chriz74x ofcourse
Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and\Illuminate\Database\Eloquent\Collections
u can use relations only on instances ofIlluminate\Database\Eloquent\Model
So what is the solution to retrieve the posts? What is the syntax?
$item_models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->get();
foreach($item_models as $item)
{
dd($item->posts()); // Now you will get the item's posts.
}
It really retrieved everything but the posts.
HasManyThrough {#232 ▼
#farParent: Item_model {#231 ▶}
#firstKey: "model_id"
#secondKey: "collected_item_id"
#localKey: "id"
#query: Builder {#228 ▶}
#parent: collected_item {#219 ▶}
#related: Post {#233 ▶}
}
jasonrust said:
chriz74x said:
jasonrust said:
Hi, chriz74x ofcourse
Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and\Illuminate\Database\Eloquent\Collections
u can use relations only on instances ofIlluminate\Database\Eloquent\Model
So what is the solution to retrieve the posts? What is the syntax?
$item_models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->get(); foreach($item_models as $item) { dd($item->posts()); // Now you will get the item's posts. }
I'm sorry but this isn't really working, only if I get the models with posts initially then I can see the posts:
$models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->with('posts')->get();
per se the method is not retrieving any post, it's the initial query that is getting those. Maybe I don't get how this hasManyThrough relation is meant to work but it doesn't seem it's retrieving anything here...
chriz74x said:
jasonrust said:
chriz74x said:
jasonrust said:
Hi, chriz74x ofcourse
Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and\Illuminate\Database\Eloquent\Collections
u can use relations only on instances ofIlluminate\Database\Eloquent\Model
So what is the solution to retrieve the posts? What is the syntax?
$item_models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->get(); foreach($item_models as $item) { dd($item->posts()); // Now you will get the item's posts. }
I'm sorry but this isn't really working, only if I get the models with posts initially then I can see the posts:
$models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->with('posts')->get();
per se the method is not retrieving any post, it's the initial query that is getting those. Maybe I don't get how this hasManyThrough relation is meant to work but it doesn't seem it's retrieving anything here...
You can't use relations on a non-object instance, to call the relation the first u must make the select (->get() or ->first()). As i understand, in your situation better to use laravel#joins, hope should it help.
jasonrust said:
chriz74x said:
jasonrust said:
chriz74x said:
jasonrust said:
Hi, chriz74x ofcourse
Call to undefined method Illuminate\Database\Query\Builder::posts()
because you can't use the relations on QueryBuilder and\Illuminate\Database\Eloquent\Collections
u can use relations only on instances ofIlluminate\Database\Eloquent\Model
So what is the solution to retrieve the posts? What is the syntax?
$item_models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->get(); foreach($item_models as $item) { dd($item->posts()); // Now you will get the item's posts. }
I'm sorry but this isn't really working, only if I get the models with posts initially then I can see the posts:
$models = Item_model::where('model_name', 'LIKE', $q . '%')->has('posts')->with('posts')->get();
per se the method is not retrieving any post, it's the initial query that is getting those. Maybe I don't get how this hasManyThrough relation is meant to work but it doesn't seem it's retrieving anything here...
You can't use relations on a non-object instance, to call the relation the first u must make the select (->get() or ->first()). As i understand in your situation u can use laravel#joins, hope should it help.
excuse me ... I am making the select with get() .. indeed I am retrieving all the models that have posts, then as suggested I am looping through the collection to retrieve the distant relation (posts).. but the point is that that method is not retrieving any post, indeed only if I retrieve the collection with('posts') then I am able to see those in the relations. But it's not the hasManyThrough method that is retrieving them, they were already there from the beginning.
Here how should show your query:
(new Collected_item)
->join("item_model", "collected_item.model_id", "=", "item_model.id")
->join("posts", "collected_item.id", "=", "posts.collected_item_id")
->select("item_model.*", "collected_item.*", "posts.*")
->where("item_model.name", 'LIKE', $q . '%')
->has('posts') // but about this statement i am care. better change this scope with true where declaration and w/e it will not work because as u can see i was changed the object query model from Item_model to Collected_item
->get();
The join method worked for me. Here's how I did it, in case someone else has the same problem. https://laracasts.com/discuss/channels/laravel/how-to-query-a-distant-relation
I decided to do away with the hasManyThroughs since I could not get them to work.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community