代碼重構
一開始練習幾乎都是寫在 controller,這樣會造成 controller 很大一包,如果把驗證、用戶創建、郵件發送的邏輯提取到單獨的方法中,可以提高代碼的可讀性和可維護性。
當然對於第 23 天:代碼質量與測試提到的測試相對會分工較細,比較能區分 Feature 和 Unit 兩類。
// 原始練習的寫法
public function register(Request $request)
{
    // 驗證輸入
    $validated = $request->validate([
        'name' => 'required|max:255',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:6|confirmed',
    ]);
    // 創建新用戶
    $user = new User();
    $user->name = $validated['name'];
    $user->email = $validated['email'];
    $user->password = bcrypt($validated['password']);
    $user->save();
    // 發送確認郵件
    Mail::to($user->email)->send(new WelcomeMail($user));
    // 返回成功響應
    return response()->json(['message' => 'User registered successfully!'], 201);
}
// 依照 clean code 原則各司其職
public function register(Request $request)
{
    $validated = $this->validateUser($request);
    $user = $this->createUser($validated);
    $this->sendWelcomeEmail($user);
    return response()->json(['message' => 'User registered successfully!'], 201);
}
private function validateUser(Request $request)
{
    return $request->validate([
        'name' => 'required|max:255',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:6|confirmed',
    ]);
}
private function createUser(array $validated)
{
    $user = new User();
    $user->name = $validated['name'];
    $user->email = $validated['email'];
    $user->password = bcrypt($validated['password']);
    $user->save();
    return $user;
}
private function sendWelcomeEmail(User $user)
{
    Mail::to($user->email)->send(new WelcomeMail($user));
}
甚至如果可以,也依照以下架構流程把方法歸類!
性能優化
一直以為後端就只要開出 api 就好,其實還講求回傳資料給前端的速度,依照使用者體驗和轉換率 google 提出載入速度若是 1~3 秒以內,直接關閉視窗的可能性大約增加 32%,但只要慢到 5 秒,關閉的可能性就會增加到 90%,所以後端也很講求速度。
我能想到的方法是快取還有從資料庫查詢速度加快!
數據庫查詢優化
使用索引來加速查詢 -> 這很常聽前輩提到加索引可以加快速度,但實際上我還沒實做過!
避免 N+1 查詢問題,使用 Eloquent 的預加載功能(with) -> 文件:模型關聯 - 預加載
預加載前:每當訪問 comments 屬性時,都會進行額外的查詢,可能導致性能問題(N+1 查詢問題)。
預加載後:在主查詢時一次性獲取所有相關的評論,減少了查詢數量,提高了效率。
// 原始練習的寫法
public function showPosts()
{
    $posts = Post::all();                        // 獲取所有文章
    foreach ($posts as $post) {
        $post->comments = $post->comments;       // 獲取每篇文章的評論
    }
    return view('posts.index', ['posts' => $posts]);
}
public function showPosts()
{
    $posts = Post::with('comments')->get();      // 預加載評論
    return view('posts.index', ['posts' => $posts]);
}
快取(Caching)
使用 Laravel 的快取系統來儲存計算結果或常用資料。
// 使用快取
Cache::put('key', 'value', $minutes);
$value = Cache::get('key');
依賴注入
通過構造函數注入依賴,讓 Laravel 的服務容器管理這些依賴,使得代碼更容易測試和維護。
public function show()
{
    $postRepository = new PostRepository(); // 直接實例化
    $posts = $postRepository->getAll();
    return view('posts.index', ['posts' => $posts]);
}
public function __construct(PostRepositoryInterface $postRepository)
{
    $this->postRepository = $postRepository;
}
public function show()
{
    $posts = $this->postRepository->getAll();
    return view('posts.index', ['posts' => $posts]);
}
工廠模式
通過工廠類來創建對象,這樣可以更容易地擴展和管理不同的通知類型,而不需要在每個地方都寫判斷邏輯。
例如,建立一個通知系統:
定義通知類別
// EmailNotification.php
class EmailNotification
{
    public function send($data)
    {
        // 實現發送郵件的邏輯
        echo "發送郵件通知: " . $data;
    }
}
// SmsNotification.php
class SmsNotification
{
    public function send($data)
    {
        // 實現發送短信的邏輯
        echo "發送短信通知: " . $data;
    }
}
定義通知工廠
文件:The InvalidArgumentException class -> 如果出現例外,這個 class 會拋出異常。
在 app/Factories 目錄下建立工廠
// NotificationFactory.php
class NotificationFactory
{
    public static function create($type)
    {
        if ($type == 'email') {
            return new EmailNotification();
        } elseif ($type == 'sms') {
            return new SmsNotification();
        }
        throw new InvalidArgumentException("未知的類型: $type");
    }
}
在 service 建立商業邏輯
下指令 mkdir app/Services 在 app 創建 Services 資料夾,並且在裡面新增一個 NotificationService.php 寫發送通知的商業邏輯
// NotificationService.php
class NotificationService
{
    public function sendNotification($type, $data)
    {
        $notification = NotificationFactory::create($type);
        $notification->send($data);
    }
}
建立 controller
建立 NotificationController.php 並且在這裡調用 NotificationService 來發送通知
// NotificationController.php
namespace App\Http\Controllers;
use App\Services\NotificationService;
class NotificationController extends Controller
{
    protected $notificationService;
    public function __construct(NotificationService $notificationService)
    {
        $this->notificationService = $notificationService;
    }
    public function sendEmail()
    {
        // 發送郵件通知
        $this->notificationService->sendNotification('email', '這是一封測試郵件!');
    }
    public function sendSms()
    {
        // 發送短信通知
        $this->notificationService->sendNotification('sms', '這是一條測試短信!');
    }
}
數據庫查詢優化以外,最近實戰過程遇到需要把資料一筆一筆存入模型中,通常都會直接用 create() 的方法
$data->each(function (User $user) {
  User::query()->create($user);
}};
但是這樣就需要一直跟資料庫重新連線,如果有模型間有關聯更會吃效能,所以 laravel 有 creatMany 的批量新增的方法可以使用,減少資料庫連線!
🔔 creatMany 需要的資料格式是 [['aaa' => ...], ['bbb' => ...]]