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.