iT邦幫忙

2023 iThome 鐵人賽

DAY 20
2

cover

昨天提到了一些部分,今天就來說到關於資料庫與預設設定的注意事項。

一定要使用 Validation

Validation 是開發 Web 應用中很重要的一個環節,除了可以確定資料的行別的正確性之外,還有驗證內容的格式是否有效,以及可以過濾一些已知的安全性問題。Laravel 本身自帶的 Validation 已經夠強大,在各種情境中都可以應付,甚至是可以使用自訂的規則去加強檢查的涵蓋範圍。

除了官方文件有列出來的部分,下面是我平時使用會用到的作法:

只取用驗證過的資料

就以官方的範例 User model 的驗證來說,rules 規則我建議都要使用 array<string>

public function rules(): array
{
    return [
        'email' => ['required', 'email', 'unique:users'],
        'name' => ['required', 'string', 'max:50'],
        'password' => 'required'
    ];
}

除了在使用上可以利用 editorsyntax highlight 幫助閱讀之外,更好去使用有特殊字元的規則。

以及要直接取用 request 物件中的 payload,要使用經過 validation 處理過的。

// Good
// $data = ['email' => 'xx', 'name' => 'xx', 'password' => 'xx']
$data = $request->validated();

// Not good
$data = $request->all();
// Not good
$email = $request->get('email');
$name = $request->get('name');

不要使用 Mass Assignment

  • 不要使用 fillable 去篩選寫入資料庫的欄位
  • 不要直接把沒有經過 validation 驗證過的資料直接寫入資料庫
// User.php
protected static $unguarded = true;

// Or

// AppServiceProvider.php
Model::unguard();

依照前一個方法從 validation 中取出驗證過的資料,不僅可以讓可讀性更好,還可以更好掌握流程控制。

$data = $request->validated();
// ...
User::query()->create($data);

不要使用 migrationdown

因為主要問題有兩點:

1. 沒有針對 migration 的 test case

就跟資料庫的備份一樣,如果沒測試的話,要使用時你有信心直接執行嗎?甚至是有確認這仍然是可以正常運作的嗎?

2. 你真的需要 rollback 嗎?

在資料庫中的紀錄是有狀態的,無法像是 codebase 一樣輕易的 rollback 並且不損失資料。很多的情況下對於資料庫的處理應該是不斷的推進,使用新的 migration 去處理變更,而不是直接 rollback

所以可以看到預設的 migration 並無針對 down function 內有其他的定義:

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

不用的 middleware 要移除

因為在多數的情況下,laravel 的專案都會以純 API Service 的形式去開發,所以記得要檢查把不需要的全端專案設定,去逐一檢查並且移除。

    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

以官方的預設版本為例,你應該就可以把 web 下所有的 middleware 都移除。

References


上一篇
#18 準備好出新手村了嗎:Laravel 進階技巧探討 (1/2)
下一篇
#20 面向使用者的第一線:Web 應用初始化
系列文
Laravel 擴展宇宙:從 1 到 100 十倍速打造產品獨角獸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
mikehsu0618
iT邦新手 1 級 ‧ 2023-10-05 22:44:42

超實用!

我要留言

立即登入留言