Laravel 代碼開發最佳實踐

      網友投稿 729 2025-04-01

      我們這里要討論的并不是 Laravel 版的 SOLID 原則(想要了解更多 SOLID 原則細節查看這篇文章)亦或是設計模式,而是 Laravel 實際開發中容易被忽略的最佳實踐。


      內容概覽

      單一職責原則

      胖模型,瘦控制器

      驗證

      業務邏輯應該放到服務類

      DRY(Don't Repeat Yourself,不要重復造輪子)

      優先使用 Eloquent 而不是查詢構建器和原生 SQL 查詢,優先使用集合而不是數組

      批量賦值

      不要在 Blade 模板中執行查詢 & 使用渴求式加載(避免 N+1 問題)

      注釋代碼

      不要把 JS 和 CSS 代碼放到 Blade 模板里面,不要在 PHP 類中寫 HTML 代碼

      使用配置、語言文件、常量而不是在代碼中寫死

      使用社區接受的標準 Laravel 工具

      遵循 Laravel 命名約定

      使用更短的、可讀性更好的語法

      使用 IoC 容器或門面而不是創建新類

      不要直接從 .env 文件獲取數據

      以標準格式存儲日期,使用訪問器和修改器來編輯日期格式

      其他好的實踐

      單一職責原則

      一個類和方法只負責一項職責。

      壞代碼:

      public function getFullNameAttribute()

      {

      if (auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified()) {

      return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' $this->last_name;

      } else {

      return $this->first_name[0] . '. ' . $this->last_name;

      }

      }

      好代碼:

      public function getFullNameAttribute()

      {

      return $this->isVerifiedClient() ? $this->getFullNameLong() : $this->getFullNameShort();

      }

      public function isVerfiedClient()

      {

      return auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified();

      }

      public function getFullNameLong()

      {

      return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;

      }

      public function getFullNameShort()

      {

      return $this->first_name[0] . '. ' . $this->last_name;

      }

      胖模型、瘦控制器

      如果你使用的是查詢構建器或原生 SQL 查詢的話將所有 DB 相關邏輯都放到 Eloquent 模型或 Repository 類。

      壞代碼:

      public function index()

      {

      $clients = Client::verified()

      ->with(['orders' => function ($q) {

      $q->where('created_at', '>', Carbon::today()->subWeek());

      }])

      ->get();

      return view('index', ['clients' => $clients]);

      }

      好代碼:

      public function index()

      {

      return view('index', ['clients' => $this->client->getWithNewOrders()]);

      }

      Class Client extends Model

      {

      public function getWithNewOrders()

      {

      return $this->verified()

      ->with(['orders' => function ($q) {

      $q->where('created_at', '>', Carbon::today()->subWeek());

      }])

      ->get();

      }

      }

      驗證

      將驗證邏輯從控制器轉移到請求類。

      壞代碼:

      public function store(Request $request)

      {

      $request->validate([

      'title' => 'required|unique:posts|max:255',

      'body' => 'required',

      'publish_at' => 'nullable|date',

      ]);

      ....

      }

      好代碼:

      public function store(PostRequest $request)

      {

      ....

      }

      class PostRequest extends Request

      {

      public function rules()

      {

      return [

      'title' => 'required|unique:posts|max:255',

      'body' => 'required',

      'publish_at' => 'nullable|date',

      ];

      }

      }

      業務邏輯需要放到服務類

      一個控制器只負責一項職責,所以需要把業務邏輯都轉移到服務類中。

      壞代碼:

      public function store(Request $request)

      {

      if ($request->hasFile('image')) {

      $request->file('image')->move(public_path('images') . 'temp');

      }

      ....

      }

      好代碼:

      public function store(Request $request)

      {

      $this->articleService->handleUploadedImage($request->file('image'));

      ....

      }

      class ArticleService

      {

      public function handleUploadedImage($image)

      {

      if (!is_null($image)) {

      $image->move(public_path('images') . 'temp');

      }

      }

      }

      DRY

      盡可能復用代碼,單一職責原則可以幫助你避免重復,此外,盡可能復用 Blade 模板,使用 Eloquent 作用域。

      壞代碼:

      public function getActive()

      {

      return $this->where('verified', 1)->whereNotNull('deleted_at')->get();

      }

      public function getArticles()

      {

      return $this->whereHas('user', function ($q) {

      $q->where('verified', 1)->whereNotNull('deleted_at');

      })->get();

      }

      好代碼:

      public function scopeActive($q)

      {

      return $q->where('verified', 1)->whereNotNull('deleted_at');

      }

      public function getActive()

      {

      return $this->active()->get();

      }

      public function getArticles()

      {

      return $this->whereHas('user', function ($q) {

      $q->active();

      })->get();

      }

      優先使用 Eloquent 和 集合

      通過 Eloquent 可以編寫出可讀性和可維護性更好的代碼,此外,Eloquent 還提供了強大的內置工具如軟刪除、事件、作用域等。

      壞代碼:

      SELECT *

      FROM `articles`

      WHERE EXISTS (SELECT *

      FROM `users`

      WHERE `articles`.`user_id` = `users`.`id`

      AND EXISTS (SELECT *

      FROM `profiles`

      WHERE `profiles`.`user_id` = `users`.`id`)

      AND `users`.`deleted_at` IS NULL)

      AND `verified` = '1'

      AND `active` = '1'

      ORDER BY `created_at` DESC

      好代碼:

      Article::has('user.profile')->verified()->latest()->get();

      批量賦值

      關于批量賦值細節可查看對應文檔。

      壞代碼:

      $article = new Article;

      $article->title = $request->title;

      $article->content = $request->content;

      $article->verified = $request->verified;

      // Add category to article

      $article->category_id = $category->id;

      $article->save();

      好代碼:

      $category->article()->create($request->all());

      不要在 Blade 執行查詢 & 使用渴求式加載

      壞代碼:

      @foreach (User::all() as $user)

      {{ $user->profile->name }}

      @endforeach

      好代碼:

      $users = User::with('profile')->get();

      ...

      @foreach ($users as $user)

      {{ $user->profile->name }}

      @endforeach

      注釋你的代碼

      壞代碼:

      if (count((array) $builder->getQuery()->joins) > 0)

      好代碼:

      // Determine if there are any joins.

      if (count((array) $builder->getQuery()->joins) > 0)

      最佳:

      if ($this->hasJoins())

      將前端代碼和 PHP 代碼分離:

      不要把 JS 和 CSS 代碼寫到 Blade 模板里,也不要在 PHP 類中編寫 HTML 代碼。

      壞代碼:

      let article = `{{ json_encode($article) }}`;

      Laravel 代碼開發最佳實踐

      好代碼:

      或者

      上一篇:vi和vim常用的三種模式
      下一篇:excel如何刪除重復數據使其只保留一個(excel刪除重復數據全部刪除不保留)
      相關文章
      亚洲大尺度无码专区尤物| 亚洲无码精品浪潮| 亚洲Av综合色区无码专区桃色| 亚洲狠狠爱综合影院婷婷| 国产综合成人亚洲区| 青草久久精品亚洲综合专区| 亚洲国产成人综合精品| 亚洲欧洲国产综合AV无码久久| 亚洲最大av资源站无码av网址| 亚洲免费视频播放| 亚洲an日韩专区在线| 精品亚洲成A人无码成A在线观看| 91亚洲性爱在线视频| 亚洲一区二区三区免费在线观看| 亚洲丰满熟女一区二区v| 91亚洲视频在线观看| 亚洲av一本岛在线播放| 亚洲中文字幕无码久久2020| 亚洲AV日韩综合一区尤物| 亚洲精华国产精华精华液网站| 亚洲国产综合AV在线观看| 成人亚洲国产精品久久| 亚洲国产综合无码一区二区二三区| 亚洲国产成人爱av在线播放| 亚洲日韩中文字幕日韩在线| 国产亚洲午夜高清国产拍精品 | 久久久久亚洲AV成人片| 少妇中文字幕乱码亚洲影视| 亚洲精品免费在线视频| 亚洲AV一二三区成人影片| 亚洲精品无码专区在线播放| 亚洲av无码av在线播放| 亚洲国产精品激情在线观看| 精品亚洲视频在线观看 | 亚洲精品国产肉丝袜久久| 亚洲人成777在线播放| 亚洲人成色在线观看| 在线观看亚洲网站| 亚洲午夜久久久久久久久久 | 亚洲精品乱码久久久久久V | 亚洲AV日韩精品久久久久久|