Reputation: 1309
The Stack
model can have "user progress", users can "clear" stacks. And that progress is stored in the Progress
model.
Progress
model:
public function stack(){
return $this->belongsTo(Stack::class);
}
It would be neat if it was possible to fetch all stacks, and if the user has "cleared" it or not, with a boolean true or false. I don't won't to fetch all data corresponding to the progress. So I have tried setting up a "finished" relation on the Stack
model
public function finished(){
return $this->hasOne(Progress::class) ? true : false;
}
But this setup gives me the following error
Call to a member function addEagerConstraints() on boolean
.
This is how I call the relationship at the moment
$user = \App\Stack::with(['finished' => function($q){
return $q->where('user_id', auth()->user()->id);
}])->get();
But that returns the whole collection, and that is not necessary. The expected result should be like:
{
"id": 5,
"user_id": 2,
"subject_id": 2,
"name": "tstar igen",
"slug": "tstar-igen",
"description": "asdasd",
"image": null,
"created_at": "2017-10-06 08:27:36",
"updated_at": "2017-10-06 08:27:36",
"finished": true/false
},
So lets say that here is an relation entry in in the progress table for the stack above.
+----+---------+----------+
| id | user_id | stack_id |
+----+---------+----------+
| 1 | 1 | 5 |
+----+---------+----------+
So when fetching the stacks, with relation finish. The finished
column should be true or false. So the return from Stack
, with relation finished
should be like the following. Notice the finished column changed to false on the last stack, because the relation is not present in the progress table.
{
"id": 5,
"user_id": 2,
"subject_id": 2,
"name": "tstar igen",
"slug": "tstar-igen",
"description": "asdasd",
"image": null,
"created_at": "2017-10-06 08:27:36",
"updated_at": "2017-10-06 08:27:36",
"finished": true
},
{
"id": 6,
"user_id": 2,
"subject_id": 2,
"name": "another stack",
"slug": "another-stack",
"description": "This is a test stack for all the stacks out there",
"image": null,
"created_at": "2017-10-06 08:27:36",
"updated_at": "2017-10-06 08:27:36",
"finished": false
},
Upvotes: 1
Views: 1845
Reputation: 87
Your model
public function progress(){
return $this->hasOne(Progress::class);
}
Your controller
...
$stacks->load('progress');
resource
'finished' => $this->whenLoaded('progress')->isNotEmpty()
Upvotes: 0
Reputation: 2604
You can try withCount
that counts your related models. But it will return number of related models not boolean. Here is an example:
Stack.php
public function progress(){
return $this->hasOne(Progress::class);
}
then:
\App\Stack::withCount('progress')->get();
Now results have count_progress
attribute with number of related 'Progress' models. Because your relation is hasOne
it should be 0 or 1.
Upvotes: 2
Reputation: 7334
You are almost done, You have your relationship setup well except for the boolean stuffs, remove it:
public function finished(){
return $this->hasOne(Progress::class);
}
Then when you need to check you can use has
or whereHas
relationship method:
$stack = \App\Stack::whereHas('finished', function($q){
return $q->where('user_id', auth()->user()->id);
})->get();
Based on your need thats the best I could conceive. I think this should be sufficient.
It would do well to learn how has and whereHas works. But just to summarize: has
simply is like whereHas
except that it checks if there is at least one model related to the first model, and the other helps you to make more advanced constraints as shown in the example I gave.
Upvotes: 1