Skip to content
Advertisement

laravel – passing data from first page to third page

I have a booking system where I divided into three steps. First, user can input the parcel weight, postcode,etc and then generate a quotation for couriers rate which brings to the next step.

Second, it shows an a list of rates for the couriers to choose and user have to select one courier and proceed to the next page which is the booking order page.

Thirdly, this page contains a form and some fields such as parcel weight, postcode , etc will be generated as you expected. So basically, I have to pass these data from 1st view all the way to the 3rd view and also the quotation rate selected from the 2nd page to the 3rd page to finalize the booking.

To summarize: parcel page(enter information parcel) -> quotation page(select a courier) -> booking order page(submit order)

web.php:

//Create new order
Route::get('/dashboard/orders','DashboardOrderController@index')->name('order.index');

//Generate quotation
Route::post('/dashboard/orders/quotation','DashboardOrderController@quotation')->name('order.quotation');

//Quotation page
Route::get('/dashboard/orders/quotation','DashboardOrderController@showQuotation')->name('quotation.show');



//Booking order page
Route::post('/dashboard/orders/booking','DashboardOrderController@createOrder')->name('create.quotation');

//Show booking order page
Route::get('dashboard/orders/booking','DashboardOrderController@showBooking')->name('show.booking');

OrderController.php:

//Create quotation
    public function quotation(Request $request){
        
        $validated = $request->validate([
            'parcel_weight' => 'required',
            'parcel_size' => 'required',
            'postcode_pickup' => 'required|postal_code:MY|exists:postcodes,postcode',
            'postcode_delivery' => 'required|postal_code:MY|exists:postcodes,postcode'
        ]);

        //logic to compute the quotation rate for each courier based on the inputs
        //default - postcode belongs to Penisular Malaysia
        $location_id = 1;

        if((88000<= $request->postcode_delivery) && ($request->postcode_delivery <= 91309) ){
            //check postcode belongs Sabah
            $location_id = 2;
        }

        if((930000<= $request->postcode_delivery) && ($request->postcode_delivery <= 98859) ){
            //check postcode belongs to Sarawak
            $location_id = 2;
        }

        $rates=Rate::where('weight',$request->parcel_weight)->where('location_id',$location_id)->get();
        
        //session()->put('submitted', true);
        return redirect()->route('quotation.show')
                         ->with('rates',$rates)
                         ->with('weight',$request->parcel_weight)
                         ->with('postcode_delivery',$request->postcode_delivery);
       
    }

    //Show quotation
    public function showQuotation(){
       //check if form is submitted
        if(session()->has('rates')){
           
            return view('orders.quotation')->with('rates',session('rates'))
                                           ->with('weight',session('weight'))
                                           ->with('postcode_delivery',session('postcode_delivery'));
        }

            abort(403);
    }

    //Show booking page
    public function createOrder(Request $request){
        //// Should be able to retrieve request from courier rate chosen, the weight of parcel, postcode
        dd($request->all());
    }

quotation.blade.php:

<div class="row">
    <div class="offset-1 col-11">
        <h4 style="font-weight: 700">Regular Order</h4>
        <p>Please select one courier:</p>
        <form method="POST" action="{{route('create.quotation')}}">
         @csrf
        <div class="row">
            @foreach($rates as $rate)
            <div class="col-3 col-md-2"> 
                <!-- ISSUE HERE------>
                 <input type="hidden" value="{{$weight}}"> 
                 <img style="height: 60px; width:80px;" src="{{asset($rate->courier->image->path .''.$rate->courier->image->filename)}}" alt="{{$rate->courier->image->filename}}">                     
                 <div>
                    <input type="radio" class="mt-1"   name="courier" value="{{$rate->cost}}">
                    <label for="{{$rate->courier->name}}">RM{{$rate->cost}}</label>        
                </div>        
            </div>
            @endforeach
        </div>
        <div class="offset-md-3 mt-4">
            <button type="submit" id="submit" class="btn" style="border-radius: 20px; background:#efcc37;">Book Delivery</button>  
        </div>
        </form>
    </div>
</div>

I am able to retrieve the data this way although I feel it might be overcomplicated of doing it. And,hidden inputs are also vulnerable as well. Is there another way of passing the data from start(1st page) all the way to the end(3rd page) without doing it my way?

How do I save the data(retrieve from 1st) in session so I can retrieve it in the final page?

Advertisement

Answer

->with('rates', $rates) or session()->push('rates', $rates) isn’t going to be valid for what you need to do here. Since $rates is an Eloquent Collection, pushing to session() wipes out all ability to search against relationships, like $rate->relationship->property. To handle this, pass along IDs and query in your GET handler:

In the handler for your POST method:

public function quotation(Request $request) {
  // ...

  $rateIds = Rate::where('weight', $request->parcel_weight)
  ->where('location_id', $location_id)
  ->pluck('id');

  return redirect()->route('quotation.show')->with([
    'rate_ids' => $rateIds,
    'weight' => $request->input('parcel_weight'),
    'postcode_delivery' => $request->input('postcode_delivery')
  ]);
}

This will return a Collection of rates.id columns from your Database. You can then pass this in Storage and query in your GET handler:

public function showQuotation(){
  if (!session()->has('rate_ids')) {
    return abort(403);
  }
  
  $rates = Rate::with('courier.image')
  ->whereIn('id', session()->get('rate_ids'))
  ->get();
  
  return view('orders.quotation')->with([
    'rates' => $rates,
    'weight' => session()->get('weight')
    'postcode_delivery' => session()->get('postcode_delivery')
  ]);
}

Now in your orders/quotation.blade.php, you can do @foreach ($rates as $rate), and $rate->relationship->property will work just fine.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement