Reputation: 2000
Although there Are some Tutorials on medium and some other sites about the Repository pattern for Laravel I read in some sites that repository pattern will duplicate the ORM and You won't need it in Laravel so now I have 2 questions: is it right to implement Repository pattern in Laravel ?? if yes What is the best source of tutorial because laracast I think has no tutorial on that neither do any good source done anything about it . and finally if not what is the best solution to make controller more beautiful and short
public function bookingPhase2(Request $request)
{
// Requests
$adults = $request->get('adults');
$children = $request->get('children') ?? 0; // number of children
$infants = $request->get('infants') ?? 0; // number of infants
$extraBed = $request->get('extra_bed') ?? 0; // number of extra services (beds)
$guestName = $request->get('guest_name'); //
$guestLastName = $request->get('guest_last_name');
$guestCellPhone = $request->get('guest_cellphone');
$guestNationality = $request->get('guest_nationality'); // ['iranian', 'other']
$guestNationalID = $request->get('guest_national_id');
$accommodationBookingId = $request->get('accommodation_booking_id');
$roomId = $request->get('room_id');
Log::info(
'The request for booking phase 2 is received with this data: ' . json_encode($request->all())
);
// Objects
$accoBookingObject = AccommodationBooking::where('id', $accommodationBookingId)->first();
$fromDate = Carbon::parse($accoBookingObject->from_date);
$toDate = Carbon::parse($accoBookingObject->to_date);
$numberOfStayingInDays = $fromDate->diffInDays($toDate);
// get accommodationRoom for validating the request
$accommodationRoom = AccommodationRoom::where('accommodation_id', $accoBookingObject->accommodation_id)->first();
$message = '';
$period = CarbonPeriod::create($accoBookingObject->from_date, $accoBookingObject->to_date);
$fPrice = [];
foreach ($period as $date) {
$formattedDate = $date->format('Y-m-d');
$roomprice = RoomPricingHistory::where('accommodation_room_id', $roomId)
->whereDate('from_date', '<=', $formattedDate)
->whereDate('to_date', '>=', $formattedDate)
->orderBy('created_at', 'desc')
->first();
if (!$roomprice) {
continue;
}
$lastPriceWithDiscount = $roomprice->sales_price - ($roomprice->sales_price * ($roomprice->discount_percent / 100));
$fPrice[] = $lastPriceWithDiscount;
}
$totalRawPrice = collect($fPrice)->sum(); // SUm of prices for each night of staying without calculating any extra charges
$pricePerNight = round($totalRawPrice / $numberOfStayingInDays, 2);
// // get accommodationRoom for validating the request
// $accommodationRoom = AccommodationRoom::where('accommodation_id', $accoBookingObject->accommodation_id)->first();
// $message = '';
if (
$children > $accommodationRoom->childs_count
) {
$message .= 'Invalid number of children which is ' . $accommodationRoom->childs_count;
} elseif ($extraBed > $accommodationRoom->extra_bed_count) {
$message .= 'Invalid number of extra bed which is ' . $accommodationRoom->extra_bed_count;
} elseif ($adults > $accommodationRoom->bed_count) {
$message .= 'Invalid number of adults which is ' . $accommodationRoom->bed_count;
}
if ($message !== '') {
return $this->sendError(
'Invalid Booking',
$message
);
}
// $accommodationObject = Accommodation::where('id', $accoBookingObject->accommodation_id)->first();
// $childAge = $accommodationObject->child_age;
// $infantAge = $accommodationObject->infant_age;;
$extraPrice = 0;
// the line below calculates the extra charges according to the children and infants during the staying nights
$extraPrice += ($pricePerNight / 2) * $children * $numberOfStayingInDays;
// extra bed price in the given period
$pricingHistory = RoomPricingHistory::where('accommodation_room_id', $roomId)
->whereDate('from_date', '<', $fromDate)->whereDate('to_date', '>', $toDate)->first();
$extraBedPrice = $pricingHistory->extra_bed_price ?? 0;
$halfChargePrice = $pricingHistory->half_charge_price ?? 0;
$halfBoardPrice = $pricingHistory->half_board_price ?? 0;
$fullBoardPrice = $pricingHistory->full_board_price ?? 0;
// final price is calculated by adding payable price and extra charge
$finalPrice = (int) round(
$totalRawPrice +
$extraPrice +
$extraBedPrice +
$halfBoardPrice +
$halfChargePrice +
$fullBoardPrice,
0
);
// Update payable price with the computed final price
AccommodationBooking::where('id', $accommodationBookingId)->update(['payable_price' => $finalPrice]);
// Add a log in accommodation_booking_accommodation_room
try {
DB::table('accommodation_booking_accommodation_room')
->insert([
'accommodation_booking_id' => $accommodationBookingId,
'accommodation_room_id' => $roomId,
'guest_national_number' => $guestNationalID,
'guest_first_name' => $guestName,
'guest_last_name' => $guestLastName,
'guest_cell_phone' => $guestCellPhone,
'guest_nationality_id' => $guestNationality,
'is_deleted' => 0,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
} catch (\Exception $ex) {
Log::error('Error during inserting accommodation_booking_accommodation_room: ' . $ex->getMessage());
return $this->sendError(
'Error during inserting accommodation_booking_accommodation_room',
'Error during inserting accommodation_booking_accommodation_room.'
);
}
return $this->sendResponse($finalPrice, 'final price retrieved successfully.');
}
Upvotes: 1
Views: 1292
Reputation: 2657
I would prefer to go with the following approach:
You can also create repository per eloquent model to interact with database however I don't really see a benefit if you don't have a plan to replace
Eloquent
in future.
Let's see some code:
php artisan make:request BookingRequest
Place all your validation in the request class and then inject it in the controller.(more about request classes) i.e:
public function bookingPhase2(BookingRequest $request)
{
// more code goes here
}
App\Services\BookingService
and add all the business logic:class BookingService
{
public function bookRooms(array $data)
{
// place your business logic here.
// you can create more private functions here to keep it more clean
// return response to requester (ie controller)
}
}
Call the service layer from controller:
public function bookingPhase2(BookingRequest $request, BookingService $bookingService)
{
try {
$response = $bookingService->bookRooms($request->validated());
// return response
} catch(\Exception $exception) {
// log error message
// throw exception
}
}
// Inject the service class in controller's constructor
// if you want to use it in other controller methods.
Read more about the service layer here
Hope it points you in a better direction!
Upvotes: 3