<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 如何使用 Service 模式 若將數據庫邏輯都寫在 Controller 里,會造成 Controller 代碼的臃腫難以維護,基于 SOLID 原則,我們應該使用 **Service** 模式輔助 Controller,將相關的業務邏輯封裝在不同的 Service,方便項目的后期維護。 ### Laravel 框架版本 Laravel 5.4.17 ## 業務邏輯 業務邏輯中,常見的如: * 牽涉到外部行為: 如 `發送 Email 郵件`,`使用外部API` .. * 使用 PHP 寫的邏輯: 如 `根據購買的數量,給予不同的折扣` ## Service ### 牽涉到外部的行為 如 `發送Email`,常常會在 Controller 中直接調用 `Mail::queue()` ``` /** * @param \Illuminate\Http\Request $request */ public function store(Request $request) { \Mail::queue('email.index', $request->all(), function (Message $message) { $message->sender(env('MAIL_USERNAME')); $message->subject(env('MAIL_SUBJECT')); $message->to(env('MAIL_TO_ADDR')); }); } ``` 在中大型的項目中,會有幾個問題: * 將牽涉到外部行為的邏輯寫在 Controller,造成 Controller 代碼臃腫難以維護 * 違反 SOLID 的單一職責原則:外部行為不應該寫在 Controller * Controller 直接相依于外部行為,使得我們無法對 Controller 做單元測試 比較好的方式是使用 Service,使用的步驟如下: * 將外部行為注入到 Service * 在 Service 使用外部行為 * 將 Service 注入到 Controlelr `app\Services\EmailService.php` ``` <?php namespace App\Services; use Illuminate\Mail\Message; use Mail; /** * Class EmailService * * @package \App\Services */ /** * Class EmailService * * @package App\Services */ class EmailService { /** * @var \Mail */ protected $mailer; /** * 將相依的 Mailer 注入到 EmailService * EmailService constructor. * * @param $mailer */ public function __construct(Mail $mailer) { $this->mailer = $mailer; } /** * 發送 Email的邏輯寫在 send() 不是使用 Mail Facade,而是使用 $this->mailer * @param array $request */ public function send(array $request) { $this->mailer->queue('email.index',$request,function(Message $message){ $message->sender(env('MAIL_USERNAME')); $message->subject(env('MAIL_SUBJECT')); $message->to(env('MAIL_TO_ADDR')); }); } } ``` `app\Controllers\UserController.php` ``` <?php namespace App\Http\Controllers; use App\Services\EmailService; use Illuminate\Http\Request; /** * Class UserController * * @package App\Http\Controllers */ class UserController extends Controller { /** * @var \App\Services\EmailService */ protected $emailService; /** * @param \Illuminate\Http\Request $request */ public function store(Request $request) { $this->emailService->send($request->all()); } } ``` 從原本相依于 `Mail Facade` ,改成相依于注入的 `EmailService`。 改用這種寫法有幾個優點,如下: * 將外部行為寫在 Service,解決了 Controller 代碼臃腫的問題。 * 符合 SOLID 的單一職責原則: 外部行為寫在 Service ,沒寫在 Controller。 * 符合 SOLID 的依賴反轉原則:Controller 并非直接相依于 Service,而是將 Service 依賴注入進 Controller。 ### 使用 PHP 寫的邏輯 如 `根據用戶購買數量,給予同步的折扣`,可能我們會在 Controller 直接寫 `if () { ... } else { ... }` 邏輯。如下`app\Controllers\UserController.php`: ``` public function index(Request $request) { $number = $request->input('number'); $price = 500; $discount = 1; if ($number == 1) { $discount = 1; } elseif ($number == 2) { $discount = 0.9; } elseif ($number == 3) { $discount = 0.8; } else { $discount = 0.7; } $total = $price * $number * $discount; return $total; } ``` 在中大型項目中,會有幾個問題: * 將 PHP 寫的業務邏輯直接寫在 Controller ,造成 Controller 的代碼臃腫難以維護 * 違反了 SOLID 的單一職責原則:業務邏輯不應該寫在 Controller * 違反了 SOLID 的單一職責原則:若未來想要改變折扣的寫算法,都需要用到此 Method,也也就是說這個 Method 同時包含了計算折扣于計算加總的職責,因此違反了 SOLID 的單一職責原則 * 直接寫在 Controller 的邏輯無法被其他 Controller 使用 `app\Services\OrderService.php` ``` <?php namespace App\Services; /** * Class OrderService * * @package App\Services */ /** * Class OrderService * * @package App\Services */ class OrderService { /** * 計算折扣 * * @param $number * * @return float */ public function getDisCount($number) { switch ($number) { case 1: return 1.0; break; case 2: return 0.9; break; case 3: return 0.8; break; default: return 0.7; } } /** * 計算最后價格 * * @param $number * @param $discount * * @return int */ public function getTotal($number, $discount) { return 500 * $number * $discount; } } ``` 在 Controller 中調用代碼,如下: ``` <?php namespace App\Http\Controllers; use App\Services\OrderService; use Illuminate\Http\Request; /** * Class UserController * * @package App\Http\Controllers */ class UserController extends Controller { /** * @var \App\Services\EmailService */ protected $orderService; /** * UserController constructor. * * @param \App\Services\OrderService $orderService */ public function __construct(OrderService $orderService) { $this->orderService = $orderService; } /** * @param \Illuminate\Http\Request $request * * @return int */ public function index(Request $request) { $number = $request->input('number'); $discount = $this->orderService->getDisCount($number); return $this->orderService->getTotal($number, $discount); } } ``` 將原本的 `if () { .. } else { .. }` 邏輯改寫成使用 `OrderService`,Controller 變得非常感覺,也達成原來 Controller 接受 Http Request,調用其他 Class 的責任。 改用這種寫法的幾個優點: * 將 PHP 寫的業務邏輯寫在 Service ,解決了 Controller 代碼臃腫的問題 * 符合 SOLID 的單一職責原則: 業務邏輯寫在 Service,沒寫在 Controller * 符合 SOLID 的單一職責原則:計算折扣與計算加總分開在不同的 Method,且歸屬于 `OrderService`,而非 `Controller` * 符合 SOLID 的依賴反轉原則: Controller 并非直接相依于 Service,而是將 Service 依賴注入進 Controller * 其他 Controller 也可以重復使用這段業務邏輯 ### 結束 * 實際上會有很多 Service ,需要自行依照 SOLID 原則去判斷是否該建立 Service * Service 使得業務邏輯從 Controller 中解放,不僅更容易維護、更容易拓展、更容易重復使用且更容易測試
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看