I have three models in my laravel project, Step
, Diploma
and Pupil
. This is what the relations look like:
class Pupil {
function steps() {
return $this->belongsToMany(Step::class);
}
function diplomas() {
return $this->belongsToMany(Diploma::class);
}
}
class Step {
function diploma() {
return $this->belongsTo(Diploma::class);
}
}
class Diploma {
function steps() {
return $this->hasMany(Step::class);
}
}
Now I have a form where the admin can check boxes of which steps a pupil has accomplished, which I then save by doing $pupil->steps()->sync($request['steps']);
. Now what I want to do is find the diplomas of which all the steps have been accomplished and sync them too. But for some reason I can't figure out how to build that query. Is this clear? Would anyone like to help?
edit I now have this, but it's not as clean as I would like:
class Pupil {
public function hasCompleted(array $completedSteps)
{
$this->steps()->sync($completedSteps);
$diplomas = [];
foreach(Diploma::all() as $diploma) {
// First see how many steps does a diploma have...
$c1 = Step::where('diploma_id', $diploma->id)->count();
// Then see how many of those we completed
$c2 = Step::where('diploma_id', $diploma->id)->whereIn('id', $completedSteps)->count();
// If that's equal, then we can add the diploma.
if ($c1 === $c2) $diplomas[] = $diploma->id;
}
$this->diplomas()->sync($diplomas);
}
}
Instead of syncing the diplomas, as the steps could change in the future, what about pulling the diplomas via the completed steps when you need to know the diplomas?
class Pupil {
public function hasCompleted(array $completedSteps) {
$this->steps()->sync($completedSteps);
}
public function getCompletedDiplomas() {
$steps = $this->steps;
$stepIds = // get the step ids
$diplomaIdsFromSteps = // get the diploma Ids from the $steps
$potentialDiplomas = Diploma::with('steps')->whereIn('id', $diplomaIdsFromSteps)->get();
$diplomas = [];
foreach($potentialDiplomas as $d) {
$diplomaSteps = $d->steps;
$diplomaStepIds = // get unique diploma ids from $diplomaSteps
if(/* all $diplomaStepIds are in $stepIds */) {
$diplomas[] = $d;
}
}
return $diplomas;
}
}
I haven't completed all the code since I'm unable to test it right now. However, I hope this points you in the right direction.