一. 前言
二. 項目規(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)境
2.3 開發(fā)專用擴展包
2.4 配置信息與環(huán)境變量
假如我們有個『CDN 域名』的變量敌买,在 Laravel 中有以下幾種方法:
- 硬代碼,直接寫死春畔。- ? 可維護性低
- 寫死在
config/app.php
文件中振峻。 - ? 無法區(qū)分環(huán)境進行配置 - 存儲于
.env
文件中,使用env()
方法直接讀取线召。 - ? 雖然解決了環(huán)境變量問題但是不推薦 - 存儲在
.env
和config/app.php
文件中铺韧,然后使用config()
函數(shù)來讀取。- ? 最佳實踐
代碼示例
.env
文件中設置:
CDN_DOMAIN=cdndomain.com
config/app.php
文件中設置:
'cdn_domain' => env('CDN_DOMAIN', null),
程序中兩種獲取 相同配置
的方法:
env('CDN_DOMAIN')
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)一
三. 編碼規(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 路由,配合資源控制器使用赁项,見 文檔葛躏。
超出 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