PHP規(guī)范 總結

參考 Laravel 項目開發(fā)規(guī)范

一. 前言

二. 項目規(guī)范

2.1 Laravel版本選擇

以下是 Laravel 的版本路線圖

版本 發(fā)布日期 版本類型 維護周期
Laravel 5.1 2015 年 6 月 LTS 長久支持 Bug 修復 2017 年 6 月份缴罗,安全修復 2018 年 6 月份
Laravel 5.2 2015 年 12 月 一般發(fā)行 提供 6 個月的 Bug 修復支持,一年的安全修復支持
Laravel 5.3 2016 年 8 月 一般發(fā)行 提供 6 個月的 Bug 修復支持掘譬,一年的安全修復支持
Laravel 5.4 2017 年 1 月 一般發(fā)行 提供 6 個月的 Bug 修復支持藐握,一年的安全修復支持
Laravel 5.5 2017 年 8 月 LTS 長久支持 Bug 修復 2019 年 8 月份袜炕,安全修復 2020 年 8 月份

選擇 Laravel 版本時陌知,應該 優(yōu)先考慮 LTS 版本,因為安全性和穩(wěn)定性考慮登刺,商業(yè)項目開發(fā)中 不應該 使用最新版本的 『Laravel 一般發(fā)行版』 。擴展閱讀:如何選擇 Laravel 框架版本

請使用以下命令來創(chuàng)建指定版本的 Laravel 項目:

composer create-project laravel/laravel project-name --prefer-dist "5.5.*"

2.2 開發(fā)和線上環(huán)境

開發(fā)和線上環(huán)境

2.3 開發(fā)專用擴展包

開發(fā)專用擴展包

2.4 配置信息與環(huán)境變量

假如我們有個『CDN 域名』的變量敌买,在 Laravel 中有以下幾種方法:

  1. 硬代碼,直接寫死春畔。- ? 可維護性低
  2. 寫死在 config/app.php 文件中振峻。 - ? 無法區(qū)分環(huán)境進行配置
  3. 存儲于 .env 文件中,使用 env() 方法直接讀取线召。 - ? 雖然解決了環(huán)境變量問題但是不推薦
  4. 存儲在 .envconfig/app.php 文件中铺韧,然后使用 config() 函數(shù)來讀取。- ? 最佳實踐

代碼示例

.env 文件中設置:

CDN_DOMAIN=cdndomain.com

config/app.php 文件中設置:

'cdn_domain' => env('CDN_DOMAIN', null),

程序中兩種獲取 相同配置 的方法:

  1. env('CDN_DOMAIN')
  2. config('app.cdn_domain')

在此統(tǒng)一規(guī)定:所有程序配置信息 必須 通過 config() 來讀取,所有的 .env 配置信息 必須 通過 config() 來讀取,絕不 在配置文件以外的范圍使用 env()白粉。

2.5 輔助函數(shù)

Laravel 提供了很多 輔助函數(shù)揽浙,有時候我們也需要創(chuàng)建自己的輔助函數(shù)。

必須 把所有的『自定義輔助函數(shù)』存放于 bootstrap 文件夾中湾盗。

并在 bootstrap/app.php 文件的最頂部進行加載:

<?php

require __DIR__ . '/helpers.php';

...

2.6 項目文檔編寫規(guī)范

文檔頁面排版 必須 遵循 中文文案排版指北 伏蚊,在此基礎上。

2.7 工具統(tǒng)一

工具統(tǒng)一

三. 編碼規(guī)范

3.1 代碼風格

代碼風格 必須 嚴格遵循 PSR-2 規(guī)范格粪。

PhpStorm設置PSR-2代碼規(guī)范躏吊,具體操作如下:

Preferences -> Editor -> Code style[PHP] -> Set From -> Predefined Style[PSR1/PSR2]

3.2 路由器

路由閉包:

絕不 在路由配置文件里書寫『閉包路由』或者其他業(yè)務邏輯代碼氛改,因為一旦使用將無法使用 路由緩存

路由器要保持干凈整潔比伏,絕不 放置除路由配置以外的其他程序邏輯胜卤。

路由命名:

必須 優(yōu)先使用 Restful 路由,配合資源控制器使用赁项,見 文檔葛躏。

img

超出 Restful 路由的,應該 模仿上圖的方式來定義路由

3.3 數(shù)據(jù)模型

位置:

所有的數(shù)據(jù)模型文件悠菜,都 必須 存放在:app/Models/ 文件夾中舰攒。

命名空間:

namespace App\Models;

使用基類:

所有的 Eloquent 數(shù)據(jù)模型必須 繼承統(tǒng)一的基類 App/Models/Model,此基類存放位置為 /app/Models/Model.php悔醋,內容參考以下:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model as EloquentModel;

class Model extends EloquentModel
{
    public function scopeRecent($query)
    {
        return $query->orderBy('created_at', 'desc');
    }
}

以 Photo 數(shù)據(jù)模型作為例子繼承 Model 基類:

<?php

namespace App\Models;

class Photo extends Model
{
    protected $fillable = ['id', 'user_id'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

命名規(guī)范:

  • 數(shù)據(jù)模型類名 必須 為「單數(shù)」, 如:App\Models\Photo
  • 類文件名 必須 為「單數(shù)」摩窃,如:app/Models/Photo.php
  • 數(shù)據(jù)庫表名字 必須 為「復數(shù)」,多個單詞情況下使用「Snake Case」 如:photos, my_photos
  • 數(shù)據(jù)庫表遷移名字 必須 為「復數(shù)」芬骄,如:2014_08_08_234417_create_photos_table.php
  • 數(shù)據(jù)填充文件名 必須 為「復數(shù)」偶芍,如:PhotosTableSeeder.php
  • 數(shù)據(jù)庫字段名 必須 為「Snake Case」,如:view_count, is_vip
  • 數(shù)據(jù)庫表主鍵 必須 為「id」
  • 數(shù)據(jù)庫表外鍵 必須 為「resource_id」德玫,如:user_id, post_id
  • 數(shù)據(jù)模型變量 必須 為「resource_id」匪蟀,如:$user_id, $post_id

關于SQL文件:

  • 絕不 使用命令行或者 PHPMyAdmin 直接創(chuàng)建索引或表。必須 使用 數(shù)據(jù)庫遷移 去創(chuàng)建表結構宰僧,并提交版本控制器中材彪;
  • 絕不 為了共享對數(shù)據(jù)庫更改就直接導出 SQL,所有修改都 必須 使用 數(shù)據(jù)庫遷移 琴儿,并提交版本控制器中段化;
  • 絕不 直接向數(shù)據(jù)庫手動寫入偽造的測試數(shù)據(jù)。必須 使用 數(shù)據(jù)填充 來插入假數(shù)據(jù)造成,并提交版本控制器中显熏。

全局作用域:

Laravel 的 Model 全局作用域 允許我們?yōu)榻o定模型的所有查詢添加默認的條件約束。

所有的全局作用域都 必須 統(tǒng)一使用 閉包定義全局作用域晒屎,如下:

/**
 * 數(shù)據(jù)模型的啟動方法
 *
 * @return void
 */
protected static function boot()
{
    parent::boot();

    static::addGlobalScope('age', function(Builder $builder) {
        $builder->where('age', '>', 200);
    });
}

3.4 控制器

必須 使用資源的復數(shù)形式喘蟆,如:

  • 類名:PhotosController
  • 文件名:PhotosController.php

3.5 視圖

https://fsdhub.com/books/laravel-specification/506/view

3.6 表單驗證

https://fsdhub.com/books/laravel-specification/507/form-validation

3.7 授權策略

授權策略:

必須 使用 授權策略 類來做用戶授權。

https://fsdhub.com/books/laravel-specification/508/policy

3.8 數(shù)據(jù)填充

factory 輔助函數(shù):

必須 使用 factory 方法來做數(shù)據(jù)填充鼓鲁,因為是框架提倡的蕴轨,并且可以同時為測試代碼服務。

運行效率:

開發(fā)數(shù)據(jù)填充時骇吭,必須 特別注意 php artisan db:seed 的運行效率橙弱,否則隨著項目的代碼量越來越大,db:seed 的運行時間會變得越來越長,有些項目多達幾分鐘甚至幾十分鐘棘脐。

原則是:

Keep it lighting speed.

只有當 db:seed 運行起來很快的時候斜筐,才能完全利用數(shù)據(jù)填充工具帶來的便利,而不是累贅蛀缝。

批量入庫:

所有假數(shù)據(jù)入庫操作顷链,都 必須 是批量操作,配合 factory 使用以下方法:

$users = factory(User::class)->times(1000)->make();
User::insert($users->toArray());

以上只執(zhí)行一條數(shù)據(jù)庫語句内斯,推薦閱讀 大批量假數(shù)據(jù)填充的正確方法蕴潦。

3.9 日期和時間

必須 使用 Carbon 來處理日期和時間相關的操作。

Laravel 5.1 中文的 diffForHumans 可以使用 jenssegers/date俘闯。

Laravel 5.3 及以上版本的 diffForHumans潭苞,只需要在 config/app.php 文件中配置 locale 選項即可 :

'locale' => 'zh-CN',

四. 其他

4.1 Laravel 安全實踐

關閉DEBUG:

Laravel Debug 開啟時,會暴露很多能被黑客利用的服務器信息真朗,所以此疹,生產環(huán)境下請 必須 確保:

APP_DEBUG=false

防XSS:

跨站腳本攻擊(cross-site scripting,簡稱 XSS)遮婶,具體危害體現(xiàn)在黑客能控制你網站頁面蝗碎,包括使用 JS 盜取 Cookie 等,關于 XSS 的介紹請前往 IBM 文檔庫:跨站點腳本攻擊深入解析 旗扑。

默認情況下蹦骑,在無法保證用戶提交內容是 100% 安全的情況下,必須 使用 Blade 模板引擎的 {{ $content }}語法會對用戶內容進行轉義臀防。

Blade 的 {!! $content !!} 語法會直接對內容進行 非轉義 輸出眠菇,使用此語法時,必須 使用 HTMLPurifier for Laravel 5 來為用戶輸入內容進行過濾袱衷。使用方法參見: 使用 HTMLPurifier 來解決 Laravel 5 中的 XSS 跨站腳本攻擊安全問題

防SQL注入:

Laravel 的 查詢構造器Eloquent 是基于 PHP 的 PDO捎废,PDO 使用 prepared 來準備查詢語句,保障了安全性致燥。

在使用 raw() 來編寫復雜查詢語句時登疗,必須 使用數(shù)據(jù)綁定。

正確操作嫌蚤,利用 select 方法 的第二個參數(shù)做數(shù)據(jù)綁定:

Route::get('sql-injection', function() {
    $name = "admin"; // 假設用戶提交
    $password = "xx' OR 1='1"; // // 假設用戶提交
    $result = DB::select(
        DB::raw("SELECT * FROM users WHERE name =:name and password = :password"),
        [
            'name' => $name,
            'password' => $password,
        ]
    );
    dd($result);
});

DB 類里的大部分執(zhí)行 SQL 的函數(shù)都可傳參第二個參數(shù) $bindings 辐益,詳見:API 文檔

批量賦值:

Laravel 提供白名單和黑名單過濾($fillable$guarded)搬葬,開發(fā)者 應該 清楚認識批量賦值安全威脅的情況下合理靈活地運用荷腊。

批量賦值安全威脅,指的是用戶可更新本來不應有權限更新的字段急凰。舉例,users 表里的 is_admin 字段是用來標識用戶『是否是管理員』,某不懷好意的用戶抡锈,更改了『修改個人資料』的表單疾忍,增加了一個字段:

<input name="is_admin" value="1" />

這個時候如果你更新代碼如下:

Auth::user()->update(Request::all());

此用戶將獲取到管理員權限〈踩可以有很多種方法來避免這種情況出現(xiàn)一罩,最簡單的方法是通過設置 User 模型里的 $guarded 字段來避免:

protected $guarded = ['id', 'is_admin'];

**CSRF: **

CSRF 跨站請求偽造是 Web 應用中最常見的安全威脅之一,具體請見 Wiki - 跨站請求偽造 或者 Web 應用程序常見漏洞 CSRF 的入侵檢測與防范撇簿。

Laravel 默認對所有『非冪等的請求』強制使用 VerifyCsrfToken 中間件防護聂渊,需要開發(fā)者做的,是區(qū)分清楚什么時候該使用『非冪等的請求』四瘫。

冪等請求指的是:'HEAD', 'GET', 'OPTIONS'汉嗽,既無論你執(zhí)行多少次重復的操作都不會給資源造成變更。

  • 所有刪除的動作找蜜,必須 使用 DELETE 作為請求方法饼暑;
  • 所有對數(shù)據(jù)更新的動作,必須 使用 POST洗做、PUT 或者 PATCH 請求方法弓叛。

4.2 Laravel 程序優(yōu)化

https://fsdhub.com/books/laravel-specification/527/laravel-optimization

4.3 代碼生成器

代碼生成器

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诚纸,隨后出現(xiàn)的幾起案子撰筷,更是在濱河造成了極大的恐慌,老刑警劉巖畦徘,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毕籽,死亡現(xiàn)場離奇詭異,居然都是意外死亡旧烧,警方通過查閱死者的電腦和手機影钉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/不壞的土叔 我叫張陵,是天一觀的道長匾鸥。 經常有香客問我蜡塌,道長,這世上最難降的妖魔是什么勿负? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任馏艾,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘琅摩。我一直安慰自己铁孵,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布房资。 她就那樣靜靜地躺著蜕劝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轰异。 梳的紋絲不亂的頭發(fā)上岖沛,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音搭独,去河邊找鬼婴削。 笑死,一個胖子當著我的面吹牛戳稽,可吹牛的內容都是我干的馆蠕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼惊奇,長吁一口氣:“原來是場噩夢啊……” “哼互躬!你這毒婦竟也來了?” 一聲冷哼從身側響起颂郎,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吼渡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后乓序,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寺酪,經...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年替劈,在試婚紗的時候發(fā)現(xiàn)自己被綠了寄雀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡陨献,死狀恐怖盒犹,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情眨业,我是刑警寧澤急膀,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站龄捡,受9級特大地震影響卓嫂,放射性物質發(fā)生泄漏。R本人自食惡果不足惜聘殖,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一晨雳、第九天 我趴在偏房一處隱蔽的房頂上張望行瑞。 院中可真熱鬧,春花似錦悍募、人聲如沸蘑辑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绷旗,卻和暖如春喜鼓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衔肢。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工庄岖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人角骤。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓隅忿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親邦尊。 傳聞我的和親對象是個殘疾皇子背桐,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355