الگوی طراحی builder در لاراول
کتابخانه الکترونیکی دیتا ساینس
الگوی طراحی builder، الگویی است که همیشه برنامه نویسان laravel، آن را در کدهای خود مشاهده میکنند. به طور مثال به کد زیر نگاه کنید:
$user = User::query() ->where('is_active', 1) ->orderBy('updated_at', 'desc') ->first();
کد فوق یک دستور Eloquent است که یک سری دستورات بعد از فراخوانی شی User، اجرا میشوند. این نمونهای از الگوی طراحی Builder است. به عبارتی where، orderBy و first متدهایی هستند که بعد از ایجاد شی از کلاس User فراخوانی میشوند. خروجی این متدها خود شی هست (return $this)، به عبارتی این متدها رفتار شی کلاس User (کاربر) را تغییر میدهند و در نهایت آن شی را به عنوان خروجی برمیگردانند.
مثال فوق، مثالی از الگوی Builder یا سازنده است و به دستورات بالا Query Builder گفته میشود.
فرض کنید شما در حال نوشتن سرویسای هستید که این سرویس باید توانایی محاسبه هزینه نهایی براساس قیمت محصول، تخفیف، مالیات و هزینه ارسال داشته باشد.
class PricingService { function calculateTotalPrice($orderPrice, $discount, $tax, $shippingFee) { return $orderPrice + $shippingFee - ($discount + $tax) } }
سرویس یا کلاس فوق به شکل زیر فراخوانی میشود.
public function show(Order $order, PricingService $service) { $totalPrice = $service->calculateTotalPrice( $order->price, $order->discount, $order->tax, $order->shippingFee ); }
کد فوق در حال حاضر ۴ آرگومان رو به تابع ارسال میکند و اگر بخواهیم در آینده چند آرگومان بیشتر به تابع ارسال کنیم، کد شما را از حالت استاندارد خارج میکند. در این حالت است که شما میتوانید از الگوی builder یا manager استفاده کنید.
class PricingService { public $orderPrice; public $discount; public $tax; public $shippingFee; public function setOrderPrice($orderPrice): PricingService { $this->orderPrice = $orderPrice; return $this; } public function setDiscount($discount): PricingService { $this->discount = $discount; return $this; } public function setTax($tax): PricingService { $this->taxPercent = $taxPercent; return $this; } public function setShippingFee($shippingFee): PricingService { $this->shippingFee = $shippingFee; return $this; } public function calculateTotalPrice() { return $this->orderPrice + $this->shippingFee - ($this->discount + $this->tax) } }
که این سرویس به شکل زیر فراخوانی میشود:
public function show(Order $order, PricingService $service) { $totalPrice = $service->setOrderPrice($order->price) ->setDiscount($order->discount) ->setTaxPercent($order->taxPercent) ->setShippingFee($order->shippingFee) ->calculateTotalPrice(); }
طبیعتا ترتیب فراخوانی setter ها اهمیتی ندارد و در آینده اگر بخواهید یه پارامتر دیگری در محاسبه هزینه اعمال کنید، کافی است یه متد setter بسازید و در متد calculateTotalPrice آن را اضافه کنید و نیازی نباشد که آرگومان اضافی به متد calculateTotalPrice ارسال کنید یا ورودی آن را تغییر دهید.
منبع: https://laraveldaily.com/post/design-patterns-laravel-builder-example