Home > Software design >  The model I passed as route parameter isn't being read (Laravel)
The model I passed as route parameter isn't being read (Laravel)

Time:12-06

In my app, after a jobseeker reviews for an exam, a new jobseekerExamReview instance is created and stored to the $examReview variable to store their score. They are then redirected to a new page that displays the results of said exam review, so I passed $examReview as a parameter to the results route. The id gets displayed in the link and works, but the content of the exam won't display as values are apparently null. I checked all the columns of the new record and they all have data. When I finally performed dd on $examReview it returns empty.

Value of $examReview (Controller):

// create new Exam review session
$examReview = jobseekerExamReview::create([
    'jobseeker_id' => $jobseeker->id,
    'exam_id' => $exam_id
    //upon creation 'results' are set to 0 at default and updated later after score calculation (see full code)
]);

Redirect in Controller:

// return view to review results with answered and correct
return redirect()->route('showResults', [$examReview]);

web.php

Route::get('/exam/reviewExam/results/{jobseekerExamReview:id}', [reviewExamController::class, 'showResults'])
    ->middleware(['auth','verified'])
    ->name('showResults');

Full code in controller:

public function calculateResult()
{
    // get needed details
    $jobseeker = Jobseeker::findorFail(auth()->user()->id);
    $exam_id = request()->input('exam_id');
    $jobApplication = jobApplication::find(session('jobApplicationId'));
    $correctAnswers = 0;

    // create new Exam review session
    $examReview = jobseekerExamReview::create([
        'jobseeker_id' => $jobseeker->id,
        'exam_id' => $exam_id
    ]);

    // loop through each question taken by user
    foreach(request()->input('taken_questions') as $key => $question_id){
        // is answer correct or not
        // echo "<br>Question ID: ".$question_id;
        $status = 0;
        //answer[questionID] => answer_id
        // if the answer[questionID] is not emptu and matched answer ID is correct
        // echo "<br>Answer ID:".request()->input('answer.'.$question_id);
        if((request()->input('answer.'.$question_id) != null) && (examAnswer::find(request()->input('answer.'.$question_id))->isCorrect == true)){
            // answer is correct
            // echo "is Correct";
            $status = 1;
            $correctAnswers  ;

            // create review Exam Answers
            jobseekerExamReviewAnswer::create([
                'exam_review_id' => $examReview->id,
                'question_id' => $question_id,
                'answer_id' => request()->input('answer.'.$question_id),
                'isCorrect' => $status
            ]);

        }
    }

    // calculate score
    $percentScore = $correctAnswers/count(request()->input('taken_questions'))*100;
    // update score in review
    $examReview->update(['result' => $percentScore]);
    // return view to review results with answered and correct
    return redirect()->route('showResults',[$examReview]);
}

public function showResults(jobseekerExamReview $examReview)
{
    return view('exams.exam-review-results',[
        'examReview' => $examReview
    ])->with('reviewExamAnswers');
}

CodePudding user response:

You have to have the name of the typehinted variable in your method signature (route action) matching the name of the route parameter in the route definition. Your route parameter is named jobseekerExamReview but the parameter to your Controller method is named jobseeker, which does not match. Because of this you are getting a new non existing instance of jobseekerExamReview injected (Dependency Injection) instead of Route Model Binding. You should adjust your route parameter to match:

Route::get('/exam/reviewExam/results/{examReview:id}', ...);

This would cause Implicit Route Model Binding to happen instead of Dependency Injection.

"Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name."

Laravel 8.x Docs - Routing - Route Model Binding - Implicit Binding

As a side note, you should get in the habit of using an associative array when passing parameters to the URL helpers, like route, so it knows exactly what parameters you are passing:

return redirect()->route('showResults', ['examReview' => $examReview]);
  • Related