Laravel Eloquent - Having trouble querying relationship with ownership - laravel

I want to get all categories and within those categories, only items that belong to the logged in user. If there are none, the category should still be there.
This is what I tried. Still getting items from other users.
$categories = Category::parents()
->with(['lineItems' => function ($query) use($id) {
$query->where('user_id', $id);
}])->get();
Haven't been able to find anything that works. (using laravel 5.7)
Relationships
Category
public function lineItems()
{
return $this->hasMany(LineItem::class);
}
LineItems
public function category()
{
return $this->belongsTo(Category::class);
}
public function user()
{
return $this->belongsTo(User::class);
}

I'm not sure where the ::parents() method is coming from (I can't find documentation for it anywhere; is it something you wrote?), but it seems like
$categories = Category::all()
->with(['lineItems' => function ($query) use ($id) {
$query->where('user_id', $id);
}])->get();
might work?

So, Travis's question made me think about my loop. My with was affecting my top level categories which left its children's line items without the where user. There's probably a more elegant method of doing this but this is what ended up working.
This queries the child's line items and the grandchild's line items.
$categories = Category::parents()->ordered()
->with(['children.lineItems' => function($q) use($id) {
$q->where('user_id', '=', $id);
}, 'children.children.lineItems' => function($q) use($id) {
$q->where('user_id', '=', $id);
}])->get();

Try this:
$categories = Category::parents()
->whereHas('lineItems', function ($query) use($id) {
$query->where('user_id', $id);
})->get();

Related

Laravel eloquent paginate in relation is not displayed in collection

I want to page the relation articles. The correct number is displayed but not in the collection, for example "first page" or "to last".
$articles = Categories::where('slug', $categorie)->with(['articles' => function ($query) use ($default_count, $default_sort) {
$query->orderBy('price', $default_sort)
->with('contents')
->paginate(2);
}])->first();
What am I missing here?
Try flipping it around so that Article is the top level:
$articles = Article::with('contents')
->whereHas('category', function ($query) use ($categorie) {
$query->where('slug', $categorie);
})
->orderBy('price', $default_sort)
->paginate(2);
This assumes that you have the category relationship set up on Article as well.
i think you want result some like that
Article::whereHas('category', function ($query) use ($categories) {
$query->where('slug', $categories);
})
->with('contents')
->orderBy('price', $default_sort)
->paginate(2);

Multilevel relationship whereHas on eloquent Model in Laravel

I'd like to find
Project::with('tasks.tags')->get();
where only projects with a particular id of tag return in the result set.
For ex. I'd like to find a project with tasks and tasks with tags with only id of 1. In other words, filter the tasks return inside of the Project - Task relationship.
I have tried various ways but have failed so far.
I have tried:
$project = Project::with('tasks.tags')->whereHas('tasks', function($query){
$query->whereHas('tags', function($query) {
$query->where('id', 1);
});
})->get();
And:
$project = Project::with('tasks.tags')->whereHas('tasks', function($query){
$query->whereHas('tags', function($query) {
$query->where('tag_id', 1);
});
})->get();
This is how the relationships are setup:
In Project.php
public function tasks()
{
return $this->hasMany(Task::class, 'project_id')->setEagerLoads([]);
}
In Task.php
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->setEagerLoads([]);
}
Note that relationship between Task and Tags is of morphToMany.
Any pointers?
You would need to scope the eager loading as well. Something like the following should work:
$project = Project::with(['tasks.tags' => function ($query) {
$query->where('id', 1);
}])->whereHas('tasks', function ($query) {
$query->whereHas('tags', function ($query) {
$query->where('id', 1);
});
})->get();
Found the answer over here.
Project::with(['tasks' => function($q) {
$q->whereHas('tags', function($query) {
$query->where('tag_id', 1);
});
}])->get();

Eloquent - How should I make a condition in a join table

I have a tournament table.
Each tournament hasMany Championships.
I want to get the tournament that match the championshipID = 333.
So, I do it :
$tournament = Tournament::with([
'championships' => function ($query) use ($request) {
$query->where('id', '=', 333);
},
'championships.settings',
'championships.category',
'championships.tree.user1',
'championships.tree.user2',
'championships.tree.user3',
'championships.tree.user4',
'championships.tree.user5'
])->first();
Example of 1 of my relations:
public function settings()
{
return $this->hasOne(ChampionshipSettings::class);
}
Tell me if you need all, to post it.
But as I put 1 eager loading relationship, I get all my tournaments instead of getting just one.
What Am I missing???
I think you're looking for whereHas() which will allow you to filter a model based on a related model's constraints. You should also use a subquery for the nested constraints if you're getting the related model more than once to avoid query duplication like:
$tournament = Tournament::whereHas('championships', function($query) use ($championshipId) {
return $query->where('id', $championshipId);
})
->with(['championships' => function ($query) use ($request) {
$query->where('id', '=', 333)
->with([
'settings',
'category',
'tree' => function($query) {
return $query->with('user1', 'user2', 'user3', 'user4', 'user5');
}]);
}])
->first();

Excluding pivot rows in Eloquent ORM query

(laravel 4.2)
There are four tables involved; users, posts, flags, and post_flags.
I want to retrieve every post a certain user has, and retrieve the flags set for the post, but only the flags that are set by the user in question.
For example: A post can have flags: 1,2,2,3 where flag 2 is set twice. Once by User A, once by User B. I don't want to see the flags that User B has set.
The Eloquent query in my controller:
$posts = Post::whereHas('companies', function($q) use($company_id) {
$q->where('id', '=', $company_id);
})->with('flags')->get();
The Relation in my Post model:
public function flags() {
return $this->belongsToMany('PostFlag', 'post_postflags', 'post_id', 'flag_id')
->withTimestamps()->withPivot('owner');
}
How would I achieve this using Eloquent ORM?
UPDATE
My final query, thanks to andrewtweber:
Final query
$posts = Post::whereHas('users', function($q) use($id) {
$q->where('id', '=', $id);
})->get()->load([
'flags' => function($query) use($id) {
$query->where('owner', '=', $id)->orWhere('owner', '=', 'SYSTEM');
}
]);
Use wherePivot
http://laravel.com/api/4.2/Illuminate/Database/Eloquent/Relations/MorphToMany.html
$flags = $post->flags()
->wherePivot('user_id', '=', $user_id)
->get();
Or with eager loading
$posts->load([
'flags' => function ($query) use($user_id) {
$query->wherePivot('user_id', '=', $user_id);
}
]);

Laravel 4 Eager Loading constraints

I want to get all Items (topics) WITH their comments, if comments user_id = $id. I try something like this, but it isn't working. So if Item hasn't got any comment with user_id = $id, then I don't need this Item.
In DiscussionsItem model I have methode:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id');
}
My query in controller is like this:
$items = DiscussionsItem::whereBrandId($brand_id)
->whereBrandCountryId($country_id)
->with(['discussionsComments' => function($query) use ($id) {
$query->where('user_id', '=', $id);
}])
->whereHas('discussionsComments', function($query) use ($id) {
$query->where('user_id', '=', $id);
})
->with(['views' => function($query) use ($id) {
$query->where('user_id', $id)->count();
}])
->orderBy('created_at', 'DESC')->get();
My problem is that I get items with comments, where comments user_id != $id.
P.S. I need to take 5 comments, but I cant imagine how to do that, because ->take(5) in my eager load is not working.
You can do a custom scope, or just limit the amount returned by your relation:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id')
->latest()
->take(5);
}

Resources