Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Ayomaid08's avatar

Laravel Validation returns blank page on failure

I have a project where several validations are working perfectly. However I added a new controller recently and noticed a break for a route. It seems that if the previous page was a POST request, 302 does not redirect to the page with its blade view but rather redirects to the page but left blank. To illustrate, see the below sequence of logic:

    public function pickstudent(Request $request){
  $term = $request->term;
  $session = $request->session;
  $stclass = $request->stclass;
  $classname = Stclass::where('id', $stclass)->first()->name;
  $students = Student::where('studentClassId', $stclass)->get(); 
  return view('admin.fees.pickstudent', compact('students', 'stclass', 'term', 'session', 'classname'));
}

admin/fees/pickstudent has a form that gets submitted to :

            public function entertransaction(Request $request){

  $term = $request->term;
  $session = $request->session;
  $banks = Bank::all();
  $stclass_id = $request->stclass;
  $student_id = $request->student_id;
  $studentname = Student::find($student_id)->surname.' '.Student::find($student_id)->firstName.' '.Student::find($student_id)->otherName;
  $students = Student::where('studentClassId', $stclass_id)->get();
  $paid = Transaction::where('student_id', $student_id)->pluck('fee_id');
  $fees= Fee::where('term', $term)->where('session', $session)->where('stclass_id', $stclass_id)->whereNotIn('id', $paid)->get();
  $officers = Role::find(4)->users()->get();

  // if($fees->isEmpty()){
  //   return back()->with('success', 'Nothing owed');
  // }

  // else{
  return view('admin.fees.entertransaction', compact('students', 'fees', 'student_id', 'studentname', 'term', 'session', 'stclass_id','banks','officers'));
}

admin/fees/entertransaction has another form that's submitted to:

    public function submitpayment(Request $request){


    $validator = Validator::make($request->all(), [
        'fees' => 'required',
        'paymentcode' => 'required',
    ]);

    if ($validator->fails()) {
        return redirect('admin/fees/pretransaction')
                    ->withErrors($validator)
                    ->withInput();
    }

    //     request()->validate([
    //      'paymentdate' => 'required',
    //     'paymentcode' => 'required|unique:transactions',
    //     'channel' => 'required',
    //     'fees' => 'required',
    //     'officer' => 'required',
    //     'bank' => 'required',
    

    // ], [
        
    //     'fees' => 'Name must be at least 2 char.',
    //     'officer' => 'Name should not be greater than 100 characters.',
    //     'paymentcode.unique' => 'A student with that Registration/Admission Number already Exists.',
    //     'bank' => 'Please check your mobile Number entry. Those are not numbers.',

    // ]);

    //   $this->validate($request, [
    //     'paymentdate' => 'required',
    //     'paymentcode' => 'required|unique:transactions',
    //     'channel' => 'required',
    //     'fees' => 'required',
    //     'officer' => 'required',
    //     'bank' => 'required',
      

    // ]);

I left the commented code so you see I have tried all validation methods I know. When validation fails, rather than return the errors to ../../entertransactions, it returns a blank .../.../entertransactions. Below is my entertransactions view:

                @extends('layouts.admin')

@section('content')

@if (count($errors) > 0)

      <ul>
          @foreach ($errors->all() as $error)
          <li>{{ $error }}</li>
          @endforeach
      </ul>
  </div>

@endif

@if ($message = Session::get('success'))
      <div class="alert alert-success">
          <p>{{ $message }}</p>
      </div>
@endif

  @if ($message = Session::get('failure'))
      <div class="alert alert-danger">
          <p>{{ $message }}</p>
      </div>
@endif

Enter Transaction

{{$studentname}} @csrf
        <thead>
            <th>Fee</th>
            <th>Amount</th>
            <th><input type="checkbox" id="feeall">Select All</th>
        </thead>
        <tbody>
    
            @foreach($fees as $fee)
            <tr>
                <td>{{$fee->name}}</td>
                <td>{{$fee->amount}}</td>
                <td><input type="checkbox" value="{{$fee->id}}" class="fees" name="fees[]" id="fees[]"></td>
            </tr>
            @endforeach
      
      
  
        </tbody>
    </table>
  <hr>
  <div class="form-group">
  <label for="channel">Payment Channel</label>
  
  <select name="channel" id="channel" class="form-control">
    <option selected="true" disabled="true">Select Payment Channel</option>
    <option value="transfer">Mobile/Internet Transfer</option>
    <option value="teller">Bank Deposit</option>
  </select>
                     
</div>



<div class="form-group">
  <label for="Class">Bank Name:</label>
 <select class="form-control" name="bank" id="bank">
  <option selected="true" disabled="true">Select Bank</option>
  @foreach($banks as $bank )
  <option value="{{ $bank->name }}">{{ $bank->name }}</option>
  @endforeach
 </select>
</div>  

   <div class="form-group">
  <label for="paymentdate">Payment Date</label>
  <input type="date" name="paymentdate" id="paymentdate" class="form-control">
</div>
  <div class="form-group">
  <label for="paymentcode">Transaction Reference(e.g Teller Number, Transfer code)</label>
  <input type="text" name="paymentcode" id="paymentcode" class="form-control">
</div>
<div class="form-group">
  <label for="payevidence">Upload Payment Evidence [Optional]</label>
  <input type="file" class="form-control-file" name="payevidence" id="payevidence">
</div>

   <div class="form-group">
  <label for="Class">Account Officer</label>
 <select class="form-control" name="officer" id="officer">
  <option selected="true" disabled="true">Select Account Officer</option>
  @foreach($officers as $officer )
  <option value="{{ $officer->id }}">{{ $officer->fullName }}</option>
  @endforeach
 </select>
</div>  
  <input type="hidden" name="student_id" value="{{$student_id}}">
   <input type="hidden" name="stclass_id" value="{{$stclass_id}}">
  <input type="hidden" name="term" value="{{$term}}">
  <input type="hidden" name="session" value="{{$session}}">
    <button type="submit" class="btn btn-success">Submit Payment</button>
</form>
</div>
$("#feeall").click(function (){ if ($("#feeall").is(':checked')){ $(".fees").each(function (){ $(this).prop("checked", true); }); }else{ $(".fees").each(function (){ $(this).prop("checked", false); }); } });
 $("#sessionall").click(function (){
 if ($("#sessionall").is(':checked')){
    $(".sessions").each(function (){
       $(this).prop("checked", true);
       });
    }else{
       $(".sessions").each(function (){
            $(this).prop("checked", false);
       });
    }

});

@stop

0 likes
3 replies
Snapey's avatar

Whenever you receive a POST in a controller ALWAYS return a redirect to a new route. NEVER return a view (or you end up with problems like this).

Ayomaid08's avatar

Thanks @snapey . You're asserting my controller should be like so?

            public function pickstudent(Request $request){
  $term = $request->term;
  $session = $request->session;
  $stclass = $request->stclass;
  $classname = Stclass::where('id', $stclass)->first()->name;
  $students = Student::where('studentClassId', $stclass)->get(); 
  return redirect()->route('pickstudent', ['term' => $term, 'session'=>$session, 'stclass'=>$stclass, 'classname'=>$classname,'students'=>$students]);
  //return view('admin.fees.pickstudent', compact('students', 'stclass', 'term', 'session', 'classname'));
}

That gives me: http://shepherd.test/admin/fees/pickstudent?term=1&session=2018%2F2019&stclass=4&classname=SSS+1F and surely a blank page. Forgive my naivety, I have never returned anything but views. Could you please show me the right way?

Snapey's avatar
Snapey
Best Answer
Level 122

If you have multiple forms that are shown in sequence, then there must also be a GET route at each step that knows how to display the next form and what data it requires.

When there is a validation error, the same GET route will be called and needs to be able to recreate the form again.

Please or to participate in this conversation.