代碼重構
一開始練習幾乎都是寫在 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' => ...]]