成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Laravel 的十八個最佳實踐

gitmilk / 2031人閱讀

摘要:本文翻譯改編自的十八個最佳實踐這篇文章并不是什么由改編的原則模式等。只是為了讓你注意你在現(xiàn)實生活的項目中最常忽略的內容。單一職責原則正在幫助你避免重復。當然,這也包括了模板的范圍等。此外,也擁有很棒的內置工具,比如軟刪除事件范圍等。

本文翻譯改編自 Laravel 的十八個最佳實踐

這篇文章并不是什么由 Laravel 改編的 SOLID 原則、模式等。

只是為了讓你注意你在現(xiàn)實生活的 Laravel 項目中最常忽略的內容。

單一責任原則

一個類和一個方法應該只有一個職責。
錯誤的做法:

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 來查詢,請將所有與數(shù)據(jù)庫相關的邏輯放入 Eloquent 模型或存儲庫類中。

壞:

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",
        ];
    }
}
業(yè)務邏輯應該在服務類中

一個控制器必須只有一個職責,因此應該將業(yè)務邏輯從控制器移到服務類。

壞:

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)

盡可能重用代碼。 SRP(單一職責原則)正在幫助你避免重復。當然,這也包括了 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 而不是 Query Builder 和原生的 SQL 查詢。要優(yōu)先于數(shù)組的集合

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 模板中執(zhí)行查詢并使用關聯(lián)加載(N + 1 問題)

不好的地方在于,這對于100 個用戶來說,等于執(zhí)行 101 個 DB 查詢:

[@foreach](https://laravel-china.org/users/5651) (User::all() as $user)
    {{ $user->profile->name }}
@endforeach

下面的做法,對于 100 個用戶來說,僅僅只執(zhí)行 2 個 DB 查詢:

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

...

[[@foreach](https://laravel-china.org/users/5651)](https://laravel-china.org/users/5651) ($users as $user)
    {{ $user->profile->name }}
@endforeach
與其花盡心思給你的代碼寫注釋,還不如對方法或變量寫一個描述性的名稱

壞:

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

好:

// 確定是否有任何連接。
if (count((array) $builder->getQuery()->joins) > 0)

最好:

if ($this->hasJoins())
不要把 JS 和 CSS 放在 Blade 模板中,也不要將任何 HTML 放在 PHP 類中

壞:

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

好:



Or

最好的方法是使用在 Javascript 中這樣來傳輸數(shù)據(jù):

let article = $("#article").val();
在代碼中使用配置和語言文件、常量,而不是寫死它

壞:

public function isNormal()
{
    return $article->type === "normal";
}

return back()->with("message", "Your article has been added!");

好:

public function isNormal()
{
    return $article->type === Article::TYPE_NORMAL;
}

return back()->with("message", __("app.article_added"));
使用社區(qū)接受的標準的 Laravel 工具

最好使用內置的 Laravel 功能和社區(qū)軟件包,而不是其他第三方軟件包和工具。因為將來與你的應用程序一起工作的開發(fā)人員都需要學習新的工具。另外,使用第三方軟件包或工具的話,如果遇到困難,從 Laravel 社區(qū)獲得幫助的機會會大大降低。不要讓你的客戶為此付出代價!

任務 標準工具 第三方工具
授權 Policies Entrust, Sentinel and other packages
前端編譯 Laravel Mix Grunt, Gulp, 3rd party packages
開發(fā)環(huán)境 Homestead Docker
部署 Laravel Forge Deployer and other solutions
單元測試 PHPUnit, Mockery Phpspec
瀏覽器測試 Laravel Dusk Codeception
數(shù)據(jù)庫操作 Eloquent SQL, Doctrine
模板 Blade Twig
數(shù)據(jù)操作 Laravel collections Arrays
表單驗證 Request classes 3rd party packages, validation in controller
認證 Built-in 3rd party packages, your own solution
API 認證 Laravel Passport 3rd party JWT and OAuth packages
創(chuàng)建 API Built-in Dingo API and similar packages
數(shù)據(jù)庫結構操作 Migrations Working with DB structure directly
局部化 Built-in 3rd party packages
實時用戶接口 Laravel Echo, Pusher 3rd party packages and working with WebSockets directly
Generating testing data Seeder classes, Model Factories, Faker Creating testing data manually
生成測試數(shù)據(jù) Laravel Task Scheduler Scripts and 3rd party packages
數(shù)據(jù)庫 MySQL, PostgreSQL, SQLite, SQL Server MongoDB
遵循Laravel命名約定

遵循 PSR 標準。 另外,請遵循 Laravel 社區(qū)接受的命名約定:

類型 規(guī)則 正確示例 錯誤示例
Controller 單數(shù) ArticleController ArticlesController
Route 復數(shù) articles/1 article/1
Named route 帶點符號的蛇形命名 users.show_active users.show-active, show-active-users
Model 單數(shù) User Users
hasOne or belongsTo relationship 單數(shù) articleComment articleComments, article_comment
All other relationships 復數(shù) articleComments articleComment, article_comments
Table 復數(shù) article_comments article_comment, articleComments
Pivot table 按字母順序排列的單數(shù)模型名稱 article_user user_article, articles_users
Table column 帶著模型名稱的蛇形命名 meta_title MetaTitle; article_meta_title
Foreign key 帶_id后綴的單數(shù)型號名稱 article_id ArticleId, id_article, articles_id
Primary key - id custom_id
Migration - 2017_01_01_000000_create_articles_table 2017_01_01_000000_articles
Method 小駝峰命名 getAll get_all
Method in resource controller 具體看表格 store saveArticle
Method in test class 小駝峰命名 testGuestCannotSeeArticle test_guest_cannot_see_article
Variable 小駝峰命名 $articlesWithAuthor $articles_with_author
Collection 具描述性的復數(shù)形式 $activeUsers = User::active()->get() $active, $data
Object 具描述性的單數(shù)形式 $activeUser = User::active()->first() $users, $obj
Config and language files index 蛇形命名 articles_enabled ArticlesEnabled; articles-enabled
View 蛇形命名 show_filtered.blade.php showFiltered.blade.php, show-filtered.blade.php
Config 蛇形命名 google_calendar.php googleCalendar.php, google-calendar.php
Contract (interface) 形容詞或名詞 Authenticatable AuthenticationInterface, IAuthentication
Trait 形容詞 Notifiable NotificationTrait
盡可能使用更短、更易讀的語法

壞:

$request->session()->get("cart");
$request->input("name");

好:

session("cart");
$request->name;

更多示例:

通用語法 更短、更可讀的語法
Session::get("cart") session("cart")
$request->session()->get("cart") session("cart")
Session::put("cart", $data) session(["cart" => $data])
$request->input("name"), Request::get("name") $request->name, request("name")
return Redirect::back() return back()
is_null($object->relation) ? $object->relation->id : null } optional($object->relation)->id
return view("index")->with("title", $title)->with("client", $client) return view("index", compact("title", "client"))
$request->has("value") ? $request->value : "default"; $request->get("value", "default")
Carbon::now(), Carbon::today() now(), today()
App::make("Class") app("Class")
->where("column", "=", 1) ->where("column", 1)
->orderBy("created_at", "desc") ->latest()
->orderBy("age", "desc") ->latest("age")
->orderBy("created_at", "asc") ->oldest()
->select("id", "name")->get() ->get(["id", "name"])
->first()->name ->value("name")
使用 IoC 容器或 facades 代替新的 Class

新的 Class 語法創(chuàng)建類時,不僅使得類與類之間緊密耦合,還加重了測試的復雜度。推薦改用 IoC 容器或 facades。

壞:

$user = new User;
$user->create($request->all());

好:

public function __construct(User $user)
{
    $this->user = $user;
}

....

$this->user->create($request->all());
不要直接從 .env 文件獲取數(shù)據(jù)

將數(shù)據(jù)傳遞給配置文件,然后使用輔助函數(shù)?config()?在應用程序中使用數(shù)據(jù)。

壞:

$apiKey = env("API_KEY");

好:

// config/api.php
"key" => env("API_KEY"),

// Use the data
$apiKey = config("api.key");
以標準格式存儲日期,必要時就使用訪問器和修改器來修改日期格式

壞:

{{ Carbon::createFromFormat("Y-d-m H-i", $object->ordered_at)->toDateString() }}
{{ Carbon::createFromFormat("Y-d-m H-i", $object->ordered_at)->format("m-d") }}

好:

// Model
protected $dates = ["ordered_at", "created_at", "updated_at"]
public function getMonthDayAttribute($date)
{
    return $date->format("m-d");
}

// View
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->monthDay }}
其他良好做法

千萬不要在路由文件中放置任何邏輯。

在 Blade 模板中最小化 vanilla PHP 的使用。

更多現(xiàn)代化 PHP 知識,請前往 Laravel / PHP 知識社區(qū)

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/28746.html

相關文章

  • Laravel 動態(tài)添加 Artisan 命令的最佳實踐

    摘要:初步嘗試既然最常見的注冊命令的方式是修改類中的,那么一般正常人都會從這邊開始下手。又要自己取出實例,又要自己調用方法,調用方法之前還有自己先把實例化這么繁瑣,肯定不是運行時添加命令的最佳實踐,所以我決定繼續(xù)尋找更優(yōu)解。 本文首發(fā)于我的博客,原文鏈接:https://blessing.studio/best-... 雖然 Laravel 官方文檔提供的添加 Artisan Command...

    ninefive 評論0 收藏0
  • Laravel最佳實踐--事件驅動編程

    摘要:事件驅動編程是圖形用戶界面和其他應用程序例如應用程序中使用的主要范例,用于執(zhí)行某些操作來響應用戶輸入。我們來看一下事件驅動編程帶來的收益?,F(xiàn)在讓我們看看采用事件驅動編程方法如何實現(xiàn)上述相同的功能。 在這篇文章中我們將了解到什么是事件驅動編程以及在Laravel中如何開始構建一個事件驅動應用,同時我們還將看到如何通過事件驅動編程來對應用程序的邏輯進行解耦。 在開始之前,先說明一下這篇文章...

    Drummor 評論0 收藏0
  • 貓頭鷹的深夜翻譯:在JAVA中記錄日志的十個小建議

    摘要:是指可能導致程序終止的非常嚴重的時間。具有最高的級別,旨在關閉中的日志功能。因此為每一個消息選擇一個合適的日志級別是非常重要的。日志的個小建議將日志訪日代碼塊它能顯著的減少因為字符串拼接而帶來的性能的影響。 前言 首先,這篇文章沒有進行任何的日志功能的詳細介紹,而是對日志提出了幾種最佳實踐。適合對日志記錄有所了解的同學閱讀。下面是正文: JAVA日志管理既是一門科學,又是一門藝術??茖W...

    venmos 評論0 收藏0
  • Laravel 5.7 最佳實踐和開發(fā)技巧分享

    摘要:當查詢數(shù)據(jù)時,本地范圍允許我們創(chuàng)建自己的查詢構造器鏈式方法。這樣便會知道這是一個本地范圍并且可以在查詢構造器中使用。某些查詢構造器不可用或者說可用但是方法名不同,關于這些請查閱所有集合的方法。 showImg(https://segmentfault.com/img/remote/1460000017877956?w=800&h=267); Laravel 因可編寫出干凈,可用可調試的...

    ninefive 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<