如何在Laravel中实现存储库模式

时间:2019-07-16 08:00:45

标签: php laravel design-patterns

尽管在媒体上有一些有关Laravel的存储库模式的教程,但在其他一些站点上我也读过一些站点,其中存储库模式将复制ORM,而您在Laravel中将不需要ORM,所以现在我有两个问题:是吗在Laravel中实施存储库模式的权利?如果是的话,最好的教程资料是什么,因为我认为laracast没有关于教程的知识,任何好的资料都没有做任何事情。最后,如果不是的话,什么是使控制器更美观,更短的最佳解决方案?

    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.');
    }

1 个答案:

答案 0 :(得分:2)

我希望采用以下方法:

  1. 创建用于数据验证的请求类
  2. 为所有业务逻辑和数据库交互创建服务类。
      

    您还可以根据雄辩的模型创建存储库以与数据库进行交互   但是,如果您将来没有替换Eloquent的计划,我不会真正受益。

让我们看一些代码:

  1. 创建请求类
php artisan make:request BookingRequest

将所有验证放入请求类中,然后将其注入控制器中。(more about request classes)即:

public function bookingPhase2(BookingRequest $request)
{
 // more code goes here
}

  1. 创建服务类App\Services\BookingService并添加所有业务逻辑:
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)
  }
}

从控制器调用服务层:

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.

详细了解service layer here

希望它会为您指明更好的方向!