I have a PaymentController
where I return to the view the registrationTypeDetails
, the total
and type_counts
. So is possible to show a summary of the registration like below. In this case the user did a registration with two participants in the registration type "general" so it should appear a summary like:
+-------------------+----------+---------+--------------+ | Registration Type | Quantity | Price | Subtotal | +-------------------+----------+---------+--------------+ | general | 2 | 10.00 € | 20.00 € | +-------------------+----------+---------+--------------+ | TOTAL | | | 20.00 € | +-------------------+----------+---------+--------------+
But it's appearing like below, with repeated info:
+-------------------+----------+---------+--------------+ | Registration Type | Quantity | Price | Subtotal | +-------------------+----------+---------+--------------+ | general | 2 | 10.00 € | 20.00 € | | general | 2 | 10.00 € | 20.00 € | +-------------------+----------+---------+--------------+ | TOTAL | | | 20.00 € | +-------------------+----------+---------+--------------+
Do you know why the info of the registration types associated with the registration are appearing twice?
In the payment.blade.php view to show the summary of the registration:
<div> <ul> <li> <span>Registration Type</span> <span>Quantity</span> <span>Price</span> <span>Subtotal</span> </li> @foreach( $registrationTypeDetails->participants as $participant ) <li> <span>{{$participant->registration_type->name}}</span> <span>{{$type_counts[$name]}}</span> <span>{{ number_format($participant->registration_type->price, 2)}}$</span> <span>{{ number_format($participant->registration_type->price * $type_counts[$name], 2)}}$</span> </li> @endforeach <li> <span>TOTAL</span> <span>{{ number_format($total, 2)}}$</span> </li> </ul> </div>
Complete code of the PaymentController
payment()
method where I get the registration types info associated with the registration and redirect the user to the payment page with this info to show a summary of the registration in the payment page.
class PaymentController extends Controller { // method that shows the payment page public function payment($id, $slug, $regID) { $regPaid = Registration::where('id', $regID)->pluck('status')->first(); // if the registration is incomplete because the user didnt pay yet if ($regPaid == "I") { // get the current user $user_id = Auth::id(); $conferenceDetails = Registration::with([ 'conference' => function ($query) { $query->select('id', 'name', 'start_date'); } ])->find($regID); $registrationTypeDetails = Registration::with(['participants.registration_type', 'participants' => function ($query) use ($regID) { $query->select('id', 'registration_type_id', 'registration_id')->where('registration_id', $regID); } ])->find($regID); $price = $registrationTypeDetails->participants->sum(function ($participant) { return $participant->registration_type->price; }); $total = $price; $totalStripe = $total * 100; if ($registrationTypeDetails->main_participant_id != $user_id) { return redirect('/'); } else { $type_counts = []; foreach ($registrationTypeDetails->participants as $p) { $name = $p->registration_type->name; if (!isset($type_counts[$name])) { $type_counts[$name] = 0; } $type_counts[$name]++; } Session::put('total', $total); Session::put('totalStripe', $totalStripe); Session::put('registrationID', $regID); $conferenceDetails = [ 'name' => $conferenceDetails->conference->name, 'start_date' => $conferenceDetails->conference->start_date ]; Session::put('conference_name', $conferenceDetails['name']); Session::put('date', $conferenceDetails['end_date']); return view('conferences.payment', compact('conferenceDetails', 'name', 'total', 'type_counts', 'registrationTypeDetails', 'id', 'slug')); } } else { Session::flash('registration_complete', 'Your registration is already paid.'); return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets'); } }
1 Answers
Answers 1
I believe the problems is coming from the way you construct your data. Use left join and methods from Model would strongly make your code more readable and helps you to debug. I don't know whether it's good or not to use with() like how you did.
Some of the functions really need to go into your model's file to make it OOP.
The way of gathering data into that conferenceDetails is a whole bunch of mess to me. I would suggest you to not only think about gathering all data you need, but also think about how the data is structured.
In your case, Conference, Registration, Participant are 3 major model. Your code messed up the relationships between each other. If your program is focused on Conference, then use Conference as the major model and get data base on it. Like:
$registrations=$conference->registrations; $participants=$conference->participants;
Not using $conference->participants() is because the participants() should return a relation not a collection whereas participants returns the collection you will need. This is done by Laravel
Now you can see, conference data is conference data, do not mess it up with participants and registrations. In your Conference model, write a function called particiants(), and in there do the work of getting data through a many to many relationship. You can find example code in Laravel docs.
In addition, I wouldn't suggest you to touch on payments if your are a starter. A payment system requires much more than what I can see from you code. The transactions, the refunds and a lot more. Even if you are using Stripe, I can still see you don't have a solid understanding of MVC programming. If I was writing this program, I would get many steps done over Ajax and provide a more user friendly interactive interface with more detailed errors and messages to help the users.
Anyway, check the code below and adjust it to fit your needs. Do not use your program on a production program, it definitely will cause nightmares. Especially when payments are related.
public function payment($id, $slug, $regID){ $reg=Registration::find($regID); //It's always good to check if the instance exists if(!$reg){ return back()->with(['error'=>'Could not find the Registration with the given ID']); } if($reg->status=='I'){ //By the way, if the status is an integer, it would be better for database design in MySQL $isRegPaid=false; } else { $isRegPaid=true; } // get the current user $user_id = Auth::id(); //remember you can also use $request->user() if the function provides Request $request as a parameter // if the registration is incomplete because the user didnt pay yet if ($isRegPaid) { $conferenceDetails = Registration::with([ 'conference' => function ($query) { $query->select('id', 'name', 'start_date'); } ])->find($regID); $conferences=Conference::where('registration_id',$regID)->get(); // $registrationTypeDetails = Registration::with(['participants.registration_type', // 'participants' => function ($query) use ($regID) { // $query->select('id', 'registration_type_id', 'registration_id')->where('registration_id', $regID); // } // ])->find($regID); $total=0; //As I don't know the actual structure of your model, I could only provide you the most basic way to sum the price //If I was writing my own code, I could do a lot more than this like left join etc. //And you also need to remember to put some of the functions into your Model, to make it more Object Oriented foreach($conferences as $conference){ //I'm assuming participants is actually a function is Conference, if it's in Registration, you will need to rewrite this part foreach($conference->participants as $participant){ $total+=$participant->registration_type->price; } } $totalStripe = $total * 100; if($reg->main_participant_id != $user_id){ //I'm guessing this main_participant_id property belongs to Registration return back()->with(['error'=>'You do not have the permission to process this payment']); //Let the user know what error they have encountered, it's good for debugging } else { $type_counts = []; foreach($conferences as $conference){ foreach($conference->participants as $participant){ $name = $participant->registration_type->name; // I don't know how you could get this name property, assuming registration_type should be a function if (!isset($type_counts[$name])) { $type_counts[$name] = 0; } $type_counts[$name]++; } } Session::put('total', $total); Session::put('totalStripe', $totalStripe); Session::put('registrationID', $regID); //You will need to rewrite this part to format your data // $conferenceDetails = [ // 'name' => $conferenceDetails->conference->name, // 'start_date' => $conferenceDetails->conference->start_date // ]; Session::put('conference_name', $conferenceDetails['name']); Session::put('date', $conferenceDetails['end_date']); // return view('conferences.payment', compact('conferences', 'name', 'total', 'type_counts', 'registrationTypeDetails', 'id', 'slug')); //ID should not need to be rendered into the view as it should be able to be accessed from Request //I don't like using compact, I usually do this: return view('conferences.payment')->with(['conferences'=>$conferences,'name'=>$name,'total'=>$total,'type_counts'=>$type_counts, 'slug'=>$slug]); } } else { Session::flash('registration_complete', 'Your registration is already paid.'); return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets'); } }
0 comments:
Post a Comment