跳到主要內容

驗證

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

驗證

簡介

Laravel 提供了幾種不同的方法來驗證應用程式的傳入資料。最常見的方法是在所有傳入的 HTTP 請求上使用 validate 方法。但是,我們也將討論其他驗證方法。

Laravel 包含各種方便的驗證規則,您可以將其應用於資料,甚至提供了驗證值在給定資料庫表中是否唯一的功能。我們將詳細介紹每種驗證規則,以便您熟悉 Laravel 的所有驗證功能。

驗證快速入門

要了解 Laravel 強大的驗證功能,讓我們查看一個完整的範例,用於驗證表單並將錯誤消息顯示給使用者。透過閱讀這個高層次概述,您將能夠很好地理解如何使用 Laravel 驗證傳入的請求資料:

定義路由

首先,讓我們假設我們在 routes/web.php 檔案中定義了以下路由:

use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

GET 路由將顯示一個表單,讓使用者建立新的部落格文章,而 POST 路由將在資料庫中儲存新的部落格文章。

建立控制器

接下來,讓我們查看一個處理這些路由的傳入請求的簡單控制器。我們將 store 方法暫時留空:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    /**
     * 顯示建立新部落格文章的表單。
     */
    public function create(): View
    {
        return view('post.create');
    }

    /**
     * 儲存新的部落格文章。
     */
    public function store(Request $request): RedirectResponse
    {
        // 驗證並儲存部落格文章...

        $post = /** ... */

        return to_route('post.show', ['post' => $post->id]);
    }
}

編寫驗證邏輯

現在我們準備好用驗證新部落格文章的邏輯來填充我們的 store 方法。為此,我們將使用 Illuminate\Http\Request 物件提供的 validate 方法。如果驗證規則透過,您的程式碼將繼續正常執行;但是,如果驗證失敗,將會拋出 Illuminate\Validation\ValidationException 異常,並且會自動向使用者發送適當的錯誤響應。

如果驗證在傳統的 HTTP 請求期間失敗,將生成一個重定向到上一個 URL 的響應。如果傳入的請求是 XHR 請求,將返回一個包含驗證錯誤消息的 JSON 響應

要更好地理解 validate 方法,讓我們回到 store 方法:

/**
 * 儲存新的部落格文章。
 */
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ]);

    // 部落格文章有效...

    return redirect('/posts');
}

如您所見,驗證規則被傳遞給 validate 方法。不要擔心——所有可用的驗證規則都已記錄在案。同樣,如果驗證失敗,將自動生成適當的響應。如果驗證透過,我們的控制器將繼續正常執行。

此外,您可以使用 validateWithBag 方法來驗證請求並將任何錯誤消息儲存在命名錯誤包中:

$validated = $request->validateWithBag('post', [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

在首次驗證失敗時停止

有時您可能希望在屬性的第一次驗證失敗後停止運行驗證規則。為此,請將 bail 規則分配給該屬性:

$request->validate([
    'title' => ['bail', 'required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

在此範例中,如果 title 屬性上的 unique 規則失敗,則不會檢查 max 規則。規則將按照分配的順序進行驗證。

關於巢狀屬性的注意事項

如果傳入的 HTTP 請求包含「巢狀」欄位資料,您可以使用「點」語法在驗證規則中指定這些欄位:

$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'author.name' => ['required'],
    'author.description' => ['required'],
]);

另一方面,如果您的欄位名稱包含字面上的句點,您可以透過用反斜線轉義句點來明確防止其被解釋為「點」語法:

$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'v1\.0' => ['required'],
]);

顯示驗證錯誤

那麼,如果傳入的請求欄位未通過給定的驗證規則怎麼辦?如前所述,Laravel 將自動將使用者重定向回其先前的位置。此外,所有驗證錯誤和請求輸入將自動閃存到 session 中

Illuminate\View\Middleware\ShareErrorsFromSession 中介層(由 web 中介層群組提供)會與您應用程式的所有視圖共享一個 $errors 變數。當此中介層被應用時,$errors 變數將始終在您的視圖中可用,允許您方便地假定 $errors 變數始終已定義並且可以安全使用。$errors 變數將是 Illuminate\Support\MessageBag 的實例。有關使用此物件的更多資訊,請查看其文檔

因此,在我們的範例中,當驗證失敗時,使用者將被重定向到我們控制器的 create 方法,允許我們在視圖中顯示錯誤消息:

<!-- /resources/views/post/create.blade.php -->

<h1>建立文章</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- 建立文章表單 -->

自訂錯誤消息

Laravel 內建的驗證規則在應用程式的 lang/en/validation.php 檔案中都有對應的錯誤消息。如果您的應用程式沒有 lang 目錄,您可以使用 lang:publish Artisan 命令指示 Laravel 建立它。

lang/en/validation.php 檔案中,您會發現每個驗證規則的翻譯條目。您可以根據應用程式的需求自由變更或修改這些消息。

此外,您可以將此檔案複製到另一個語言目錄中,以翻譯應用程式語言的消息。要了解更多關於 Laravel 本地化的資訊,請查看完整的本地化文檔

[!WARNING] 預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自訂 Laravel 的語言檔案,可以使用 lang:publish Artisan 命令發布它們。

XHR 請求和驗證

在此範例中,我們使用傳統表單向應用程式傳送資料。但是,許多應用程式從 JavaScript 驅動的前端接收 XHR 請求。在 XHR 請求期間使用 validate 方法時,Laravel 不會生成重定向響應。相反,Laravel 生成一個包含所有驗證錯誤的 JSON 響應。此 JSON 響應將以 422 HTTP 狀態碼發送。

@error 指令

您可以使用 @error Blade 指令快速判斷給定屬性是否存在驗證錯誤消息。在 @error 指令中,您可以輸出 $message 變數來顯示錯誤消息:

<!-- /resources/views/post/create.blade.php -->

<label for="title">文章標題</label>

<input
    id="title"
    type="text"
    name="title"
    class="@error('title') is-invalid @enderror"
/>

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

如果您正在使用命名錯誤包,您可以將錯誤包的名稱作為第二個參數傳遞給 @error 指令:

<input ... class="@error('title', 'post') is-invalid @enderror">

重新填充表單

當 Laravel 因驗證錯誤生成重定向響應時,框架將自動將所有請求的輸入閃存到 session 中。這樣做的目的是讓您可以在下次請求期間方便地存取輸入,並重新填充使用者嘗試提交的表單。

要從先前的請求中檢索閃存的輸入,請在 Illuminate\Http\Request 的實例上調用 old 方法。old 方法將從session 中提取先前閃存的輸入資料:

$title = $request->old('title');

Laravel 還提供了一個全域 old 輔助函數。如果您在 Blade 模板中顯示舊輸入,使用 old 輔助函數重新填充表單會更方便。如果給定欄位不存在舊輸入,將返回 null

<input type="text" name="title" value="{{ old('title') }}">

關於可選欄位的注意事項

預設情況下,Laravel 在應用程式的全域中介層堆疊中包含 TrimStringsConvertEmptyStringsToNull 中介層。因此,如果您不希望驗證器將 null 值視為無效,則通常需要將您的「可選」請求欄位標記為 nullable。例如:

$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
    'publish_at' => ['nullable', 'date'],
]);

在此範例中,我們指定 publish_at 欄位可以是 null 或有效的日期表示。如果規則定義中未添加 nullable 修飾符,驗證器將認為 null 是無效的日期。

驗證錯誤響應格式

當您的應用程式拋出 Illuminate\Validation\ValidationException 異常並且傳入的 HTTP 請求期望 JSON 響應時,Laravel 將自動為您格式化錯誤消息並返回 422 Unprocessable Entity HTTP 響應。

下面,您可以查看驗證錯誤的 JSON 響應格式範例。請注意,巢狀錯誤金鑰被扁平化為「點」語法格式:

{
    "message": "團隊名稱必須是字串。(還有 4 個錯誤)",
    "errors": {
        "team_name": [
            "團隊名稱必須是字串。",
            "團隊名稱至少必須有 1 個字元。"
        ],
        "authorization.role": [
            "所選的 authorization.role 無效。"
        ],
        "users.0.email": [
            "users.0.email 欄位是必填的。"
        ],
        "users.2.email": [
            "users.2.email 必須是有效的電子郵件地址。"
        ]
    }
}

表單請求驗證

建立表單請求

對於更複雜的驗證場景,您可能希望建立一個「表單請求」。表單請求是自訂請求類別,封裝了它們自己的驗證和授權邏輯。要建立表單請求類別,您可以使用 make:request Artisan CLI 命令:

php artisan make:request StorePostRequest

生成的表單請求類別將放置在 app/Http/Requests 目錄中。如果此目錄不存在,當您運行 make:request 命令時它將被建立。Laravel 生成的每個表單請求都有兩個方法:authorizerules

正如您可能已經猜到的,authorize 方法負責判斷當前已驗證的使用者是否可以執行請求所代表的操作,而 rules 方法返回應應用於請求資料的驗證規則:

/**
 * 獲取應用於請求的驗證規則。
 *
 * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
 */
public function rules(): array
{
    return [
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ];
}

[!NOTE] 您可以在 rules 方法的簽名中類型提示您需要的任何依賴項。它們將透過 Laravel 服務容器自動解析。

那麼,驗證規則是如何評估的呢?您只需在控制器方法上類型提示請求即可。傳入的表單請求在控制器方法被調用之前進行驗證,這意味著您無需用任何驗證邏輯使您的控制器變得混亂:

/**
 * 儲存新的部落格文章。
 */
public function store(StorePostRequest $request): RedirectResponse
{
    // 傳入的請求有效...

    // 檢索已驗證的輸入資料...
    $validated = $request->validated();

    // 檢索已驗證輸入資料的一部分...
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);

    // 儲存部落格文章...

    return redirect('/posts');
}

如果驗證失敗,將生成重定向響應以將使用者送回其先前的位置。錯誤也將閃存到 session 中,以便它們可用於顯示。如果請求是 XHR 請求,將向使用者返回一個帶有 422 狀態碼的 HTTP 響應,其中包含驗證錯誤的 JSON 表示

[!NOTE] 需要將即時表單請求驗證添加到您的 Inertia 驅動的 Laravel 前端嗎?請查看 Laravel Precognition

執行額外驗證

有時您需要在初始驗證完成後執行額外驗證。您可以使用表單請求的 after 方法來完成此操作。

after 方法應返回一個可調用物件或閉包陣列,這些物件將在驗證完成後被調用。給定的可調用物件將接收一個 Illuminate\Validation\Validator 實例,允許您在必要時引發額外的錯誤消息:

use Illuminate\Validation\Validator;

/**
 * 獲取請求的「後續」驗證可調用物件。
 */
public function after(): array
{
    return [
        function (Validator $validator) {
            if ($this->somethingElseIsInvalid()) {
                $validator->errors()->add(
                    'field',
                    '此欄位有問題!'
                );
            }
        }
    ];
}

如前所述,after 方法返回的陣列還可以包含可調用類別。這些類別的 __invoke 方法將接收一個 Illuminate\Validation\Validator 實例:

use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;

/**
 * 獲取請求的「後續」驗證可調用物件。
 */
public function after(): array
{
    return [
        new ValidateUserStatus,
        new ValidateShippingTime,
        function (Validator $validator) {
            //
        }
    ];
}

在首次驗證失敗時停止

透過將 StopOnFirstFailure 屬性添加到您的請求類別,您可以通知驗證器它應該在發生單個驗證失敗後停止驗證所有屬性:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
use Illuminate\Foundation\Http\FormRequest;

#[StopOnFirstFailure]
class StorePostRequest extends FormRequest
{
    // ...
}

在未知欄位時失敗

透過將 FailOnUnknownFields 屬性添加到您的請求類別,您可以指示 Laravel 拒絕未由請求的驗證規則定義的任何傳入欄位:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\FailOnUnknownFields;
use Illuminate\Foundation\Http\FormRequest;

#[FailOnUnknownFields]
class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => ['required', 'string'],
            'body' => ['required', 'string'],
        ];
    }
}

您也可以從 AppServiceProvider 為所有表單請求全域啟用此行為:

use Illuminate\Foundation\Http\FormRequest;

/**
 * 引導任何應用程式服務。
 */
public function boot(): void
{
    FormRequest::failOnUnknownFields();
}

如有需要,您可以透過向屬性傳遞 false 來為特定請求禁用此行為:

#[FailOnUnknownFields(false)]
class PublicWebhookRequest extends FormRequest
{
    // ...
}

拒絕未知欄位可以透過防止意外的輸入金鑰深入流入應用程式來提供額外的保護,防止批量賦值風格的問題。但是,您仍應配置模型的 $fillable / $guarded 屬性,並且只持久化可信的、已驗證的輸入。

自訂重定向位置

當表單請求驗證失敗時,將生成重定向響應以將使用者送回其先前的位置。但是,您可以自由地自訂此行為。為此,您可以在表單請求上使用 RedirectTo 屬性:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\RedirectTo;
use Illuminate\Foundation\Http\FormRequest;

#[RedirectTo('/dashboard')]
class StorePostRequest extends FormRequest
{
    // ...
}

或者,如果您想將使用者重定向到具名路由,您可以改用 RedirectToRoute 屬性:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
use Illuminate\Foundation\Http\FormRequest;

#[RedirectToRoute('dashboard')]
class StorePostRequest extends FormRequest
{
    // ...
}

自訂錯誤包

當表單請求驗證失敗時,錯誤會閃存到 default 錯誤包中。如果您需要將錯誤儲存在不同的命名錯誤包中,您可以在表單請求上使用 ErrorBag 屬性:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\ErrorBag;
use Illuminate\Foundation\Http\FormRequest;

#[ErrorBag('login')]
class LoginRequest extends FormRequest
{
    // ...
}

授權表單請求

表單請求類別還包含一個 authorize 方法。在此方法中,您可以判斷已驗證的使用者是否實際有權更新給定的資源。例如,您可以判斷使用者是否實際擁有他們嘗試更新的部落格評論。大多數情況下,您將在此方法中與您的授權閘道和策略互動:

use App\Models\Comment;

/**
 * 判斷使用者是否有權發出此請求。
 */
public function authorize(): bool
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

由於所有表單請求都繼承了基礎 Laravel 請求類別,我們可以使用 user 方法來存取當前已驗證的使用者。此外,請注意上面範例中對 route 方法的調用。此方法授予您存取路由上定義的 URI 參數的權限,例如下面範例中的 {comment} 參數:

Route::post('/comment/{comment}');

因此,如果您的應用程式利用了路由模型綁定,您可以透過將解析的模型作為請求的屬性來存取,使您的程式碼更加簡潔:

return $this->user()->can('update', $this->comment);

如果 authorize 方法返回 false,將自動返回帶有 403 狀態碼的 HTTP 響應,並且您的控制器方法將不會執行。

如果您計劃在應用程式的其他部分處理請求的授權邏輯,您可以完全移除 authorize 方法,或者只需返回 true

/**
 * 判斷使用者是否有權發出此請求。
 */
public function authorize(): bool
{
    return true;
}

[!NOTE] 您可以在 authorize 方法的簽名中類型提示您需要的任何依賴項。它們將透過 Laravel 服務容器自動解析。

自訂錯誤消息

您可以透過覆蓋 messages 方法來自訂表單請求使用的錯誤消息。此方法應返回一個屬性/規則對及其相應錯誤消息的陣列:

/**
 * 獲取定義的驗證規則的錯誤消息。
 *
 * @return array<string, string>
 */
public function messages(): array
{
    return [
        'title.required' => '標題是必填的',
        'body.required' => '內文是必填的',
    ];
}

自訂驗證屬性

Laravel 許多內建的驗證規則錯誤消息包含一個 :attribute 佔位符。如果您希望驗證消息的 :attribute 佔位符被替換為自訂屬性名稱,您可以透過覆蓋 attributes 方法來指定自訂名稱。此方法應返回一個屬性/名稱對的陣列:

/**
 * 獲取驗證錯誤的自訂屬性。
 *
 * @return array<string, string>
 */
public function attributes(): array
{
    return [
        'email' => '電子郵件地址',
    ];
}

為驗證準備輸入

如果您需要在應用驗證規則之前從請求中準備或清理任何資料,您可以使用 prepareForValidation 方法:

use Illuminate\Support\Str;

/**
 * 為驗證準備資料。
 */
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

同樣,如果您需要在驗證完成後標準化任何請求資料,您可以使用 passedValidation 方法:

/**
 * 處理已透過的驗證嘗試。
 */
protected function passedValidation(): void
{
    $this->replace(['name' => 'Taylor']);
}

手動建立驗證器

如果您不想使用請求上的 validate 方法,您可以使用 Validator Facade手動建立驗證器實例。Facade 上的 make 方法生成一個新的驗證器實例:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    /**
     * 儲存新的部落格文章。
     */
    public function store(Request $request): RedirectResponse
    {
        $validator = Validator::make($request->all(), [
            'title' => ['required', 'unique:posts', 'max:255'],
            'body' => ['required'],
        ]);

        if ($validator->fails()) {
            return redirect('/post/create')
                ->withErrors($validator)
                ->withInput();
        }

        // 檢索已驗證的輸入...
        $validated = $validator->validated();

        // 檢索已驗證輸入的一部分...
        $validated = $validator->safe()->only(['name', 'email']);
        $validated = $validator->safe()->except(['name', 'email']);

        // 儲存部落格文章...

        return redirect('/posts');
    }
}

傳遞給 make 方法的第一個參數是正在驗證的資料。第二個參數是要應用於資料的驗證規則陣列。

在判斷請求驗證是否失敗後,您可以使用 withErrors 方法將錯誤消息閃存到 session 中。使用此方法時,$errors 變數將在重定向後自動與您的視圖共享,允許您輕鬆地將其顯示回使用者。withErrors 方法接受一個驗證器、一個 MessageBag 或一個 PHP array

在首次驗證失敗時停止

stopOnFirstFailure 方法將通知驗證器它應該在發生單個驗證失敗後停止驗證所有屬性:

if ($validator->stopOnFirstFailure()->fails()) {
    // ...
}

自動重定向

如果您想手動建立驗證器實例,但仍想利用 HTTP 請求的 validate 方法提供的自動重定向,您可以在現有驗證器實例上調用 validate 方法。如果驗證失敗,使用者將自動被重定向,或者在 XHR 請求的情況下,將返回 JSON 響應

Validator::make($request->all(), [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
])->validate();

您可以使用 validateWithBag 方法在驗證失敗時將錯誤消息儲存在命名錯誤包中:

Validator::make($request->all(), [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
])->validateWithBag('post');

命名錯誤包

如果您在單個頁面上有多個表單,您可能希望命名包含驗證錯誤的 MessageBag,允許您檢索特定表單的錯誤消息。為此,將名稱作為第二個參數傳遞給 withErrors

return redirect('/register')->withErrors($validator, 'login');

您可以從 $errors 變數中存取命名的 MessageBag 實例:

{{ $errors->login->first('email') }}

自訂錯誤消息

如有需要,您可以提供驗證器實例應使用的自訂錯誤消息,而不是 Laravel 提供的預設錯誤消息。有幾種方法可以指定自訂消息。首先,您可以將自訂消息作為第三個參數傳遞給 Validator::make 方法:

$validator = Validator::make($input, $rules, $messages = [
    'required' => ':attribute 欄位是必填的。',
]);

在此範例中,:attribute 佔位符將被替換為正在驗證的欄位的實際名稱。您還可以在驗證消息中使用其他佔位符。例如:

$messages = [
    'same' => ':attribute 和 :other 必須匹配。',
    'size' => ':attribute 必須恰好是 :size。',
    'between' => ':attribute 值 :input 不在 :min - :max 之間。',
    'in' => ':attribute 必須是以下類型之一::values',
];

為給定屬性指定自訂消息

有時您可能只想為特定屬性指定自訂錯誤消息。您可以使用「點」語法來完成此操作。首先指定屬性的名稱,然後是規則:

$messages = [
    'email.required' => '我們需要知道您的電子郵件地址!',
];

指定自訂屬性值

Laravel 許多內建的錯誤消息包含一個 :attribute 佔位符,它將被替換為正在驗證的欄位或屬性的名稱。要自訂用於替換特定欄位的這些佔位符的值,您可以將自訂屬性陣列作為第四個參數傳遞給 Validator::make 方法:

$validator = Validator::make($input, $rules, $messages, [
    'email' => '電子郵件地址',
]);

執行額外驗證

有時您需要在初始驗證完成後執行額外驗證。您可以使用驗證器的 after 方法來完成此操作。after 方法接受一個閉包或一個可調用物件陣列,這些物件將在驗證完成後被調用。給定的可調用物件將接收一個 Illuminate\Validation\Validator 實例,允許您在必要時引發額外的錯誤消息:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make(/* ... */);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add(
            'field', '此欄位有問題!'
        );
    }
});

if ($validator->fails()) {
    // ...
}

如前所述,after 方法還接受一個可調用物件陣列,如果您的「驗證後」邏輯封裝在可調用類別中,這特別方便,這些類別將透過其 __invoke 方法接收一個 Illuminate\Validation\Validator 實例:

use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;

$validator->after([
    new ValidateUserStatus,
    new ValidateShippingTime,
    function ($validator) {
        // ...
    },
]);

處理已驗證的輸入

使用表單請求或手動建立的驗證器實例驗證傳入的請求資料後,您可能希望檢索實際經過驗證的傳入請求資料。這可以透過幾種方式完成。首先,您可以在表單請求或驗證器實例上調用 validated 方法。此方法返回已驗證的資料陣列:

$validated = $request->validated();

$validated = $validator->validated();

或者,您可以在表單請求或驗證器實例上調用 safe 方法。此方法返回 Illuminate\Support\ValidatedInput 的實例。此物件公開 onlyexceptall 方法,以檢索已驗證資料的子集或整個已驗證資料陣列:

$validated = $request->safe()->only(['name', 'email']);

$validated = $request->safe()->except(['name', 'email']);

$validated = $request->safe()->all();

此外,Illuminate\Support\ValidatedInput 實例可以像陣列一樣被迭代和存取:

// 已驗證的資料可以被迭代...
foreach ($request->safe() as $key => $value) {
    // ...
}

// 已驗證的資料可以像陣列一樣被存取...
$validated = $request->safe();

$email = $validated['email'];

如果您想向已驗證的資料添加額外的欄位,可以調用 merge 方法:

$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);

如果您想將已驗證的資料作為集合實例檢索,可以調用 collect 方法:

$collection = $request->safe()->collect();

處理錯誤消息

Validator 實例上調用 errors 方法後,您將收到一個 Illuminate\Support\MessageBag 實例,它提供了多種方便的方法來處理錯誤消息。自動提供給所有視圖的 $errors 變數也是 MessageBag 類別的實例。

檢索欄位的第一個錯誤消息

要檢索給定欄位的第一個錯誤消息,請使用 first 方法:

$errors = $validator->errors();

echo $errors->first('email');

檢索欄位的所有錯誤消息

如果您需要檢索給定欄位的所有消息的陣列,請使用 get 方法:

foreach ($errors->get('email') as $message) {
    // ...
}

如果您正在驗證陣列表單欄位,您可以使用 * 字元檢索陣列每個元素的所有消息:

foreach ($errors->get('attachments.*') as $message) {
    // ...
}

檢索所有欄位的所有錯誤消息

要檢索所有欄位的所有消息的陣列,請使用 all 方法:

foreach ($errors->all() as $message) {
    // ...
}

判斷欄位是否存在錯誤消息

has 方法可用於判斷給定欄位是否存在任何錯誤消息:

if ($errors->has('email')) {
    // ...
}

在語言檔案中指定自訂消息

Laravel 內建的驗證規則在應用程式的 lang/en/validation.php 檔案中都有對應的錯誤消息。如果您的應用程式沒有 lang 目錄,您可以使用 lang:publish Artisan 命令指示 Laravel 建立它。

lang/en/validation.php 檔案中,您會發現每個驗證規則的翻譯條目。您可以根據應用程式的需求自由變更或修改這些消息。

此外,您可以將此檔案複製到另一個語言目錄中,以翻譯應用程式語言的消息。要了解更多關於 Laravel 本地化的資訊,請查看完整的本地化文檔

[!WARNING] 預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自訂 Laravel 的語言檔案,可以使用 lang:publish Artisan 命令發布它們。

為特定屬性指定自訂消息

您可以在應用程式的驗證語言檔案中自訂用於指定屬性和規則組合的錯誤消息。為此,將您的消息自訂添加到應用程式的 lang/xx/validation.php 語言檔案的 custom 陣列中:

'custom' => [
    'email' => [
        'required' => '我們需要知道您的電子郵件地址!',
        'max' => '您的電子郵件地址太長了!'
    ],
],

在語言檔案中指定屬性

Laravel 許多內建的錯誤消息包含一個 :attribute 佔位符,它將被替換為正在驗證的欄位或屬性的名稱。如果您希望驗證消息的 :attribute 部分被替換為自訂值,您可以在 lang/xx/validation.php 語言檔案的 attributes 陣列中指定自訂屬性名稱:

'attributes' => [
    'email' => '電子郵件地址',
],

[!WARNING] 預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自訂 Laravel 的語言檔案,可以使用 lang:publish Artisan 命令發布它們。

在語言檔案中指定值

Laravel 一些內建的驗證規則錯誤消息包含一個 :value 佔位符,它將被替換為請求屬性的當前值。但是,您可能偶爾需要驗證消息的 :value 部分被替換為值的自訂表示。例如,考慮以下規則,它指定如果 payment_type 的值為 cc,則需要信用卡號:

Validator::make($request->all(), [
    'credit_card_number' => ['required_if:payment_type,cc']
]);

如果此驗證規則失敗,它將產生以下錯誤消息:

當付款類型為 cc 時,信用卡號欄位是必填的。

不是顯示 cc 作為付款類型值,您可以透過在 lang/xx/validation.php 語言檔案中定義 values 陣列來指定更使用者友好的值表示:

'values' => [
    'payment_type' => [
        'cc' => '信用卡'
    ],
],

[!WARNING] 預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自訂 Laravel 的語言檔案,可以使用 lang:publish Artisan 命令發布它們。

定義此值後,驗證規則將產生以下錯誤消息:

當付款類型為信用卡時,信用卡號欄位是必填的。

可用的驗證規則

以下是所有可用驗證規則及其功能的列表:

布林值

字串

數字

陣列

日期

檔案

資料庫

實用工具

accepted

正在驗證的欄位必須是 "yes""on"1"1"true"true"。這對於驗證「服務條款」接受或類似欄位很有用。

accepted_if:anotherfield,value,...

如果另一個正在驗證的欄位等於指定的值,則正在驗證的欄位必須是 "yes""on"1"1"true"true"。這對於驗證「服務條款」接受或類似欄位很有用。

active_url

正在驗證的欄位必須根據 dns_get_record PHP 函數具有有效的 A 或 AAAA 記錄。在傳遞給 dns_get_record 之前,使用 parse_url PHP 函數提取提供的 URL 的主機名。

after:date

正在驗證的欄位必須是給定日期之後的值。日期將被傳遞給 strtotime PHP 函數以轉換為有效的 DateTime 實例:

'start_date' => ['required', 'date', 'after:tomorrow']

不是傳遞要由 strtotime 評估的日期字串,您可以指定另一個欄位與日期進行比較:

'finish_date' => ['required', 'date', 'after:start_date']

為了方便,基於日期的規則可以使用流暢的 date 規則建構器來建立:

use Illuminate\Validation\Rule;

'start_date' => [
    'required',
    Rule::date()->after(today()->addDays(7)),
],

afterTodaytodayOrAfter 方法可用於流暢地表達日期必須在今天之後,或今天或之後:

'start_date' => [
    'required',
    Rule::date()->afterToday(),
],

after_or_equal:date

正在驗證的欄位必須是給定日期之後或等於的值。有關更多資訊,請參閱 after 規則。

為了方便,基於日期的規則可以使用流暢的 date 規則建構器來建立:

use Illuminate\Validation\Rule;

'start_date' => [
    'required',
    Rule::date()->afterOrEqual(today()->addDays(7)),
],

anyOf

Rule::anyOf 驗證規則允許您指定正在驗證的欄位必須滿足給定的任何驗證規則集。例如,以下規則將驗證 username 欄位是電子郵件地址或至少 6 個字元長的字母數字字串(包括破折號):

use Illuminate\Validation\Rule;

'username' => [
    'required',
    Rule::anyOf([
        ['string', 'email'],
        ['string', 'alpha_dash', 'min:6'],
    ]),
],

alpha

正在驗證的欄位必須完全是包含在 \p{L}\p{M} 中的 Unicode 字母字元。

要將此驗證規則限制為 ASCII 範圍內的字元(a-zA-Z),您可以向驗證規則提供 ascii 選項:

'username' => ['alpha:ascii'],

alpha_dash

正在驗證的欄位必須完全是包含在 \p{L}\p{M}\p{N} 以及 ASCII 破折號(-)和 ASCII 下劃線(_)中的 Unicode 字母數字字元。

要將此驗證規則限制為 ASCII 範圍內的字元(a-zA-Z0-9),您可以向驗證規則提供 ascii 選項:

'username' => ['alpha_dash:ascii'],

alpha_num

正在驗證的欄位必須完全是包含在 \p{L}\p{M}\p{N} 中的 Unicode 字母數字字元。

要將此驗證規則限制為 ASCII 範圍內的字元(a-zA-Z0-9),您可以向驗證規則提供 ascii 選項:

'username' => ['alpha_num:ascii'],

array

正在驗證的欄位必須是一個 PHP array

當向 array 規則提供額外值時,輸入陣列中的每個金鑰必須存在於提供給規則的值列表中。在以下範例中,輸入陣列中的 admin 金鑰是無效的,因為它不包含在提供給 array 規則的值列表中:

use Illuminate\Support\Facades\Validator;

$input = [
    'user' => [
        'name' => 'Taylor Otwell',
        'username' => 'taylorotwell',
        'admin' => true,
    ],
];

Validator::make($input, [
    'user' => ['array:name,username'],
]);

通常,您應該始終指定允許存在於陣列中的陣列金鑰。

ascii

正在驗證的欄位必須完全是 7 位元 ASCII 字元。

bail

在第一次驗證失敗後停止運行該欄位的驗證規則。

雖然 bail 規則只會在遇到驗證失敗時停止驗證特定欄位,但 stopOnFirstFailure 方法將通知驗證器它應該在發生單個驗證失敗後停止驗證所有屬性:

if ($validator->stopOnFirstFailure()->fails()) {
    // ...
}

before:date

正在驗證的欄位必須是給定日期之前的值。日期將被傳遞給 PHP strtotime 函數以轉換為有效的 DateTime 實例。此外,像 after 規則一樣,可以將另一個正在驗證的欄位名稱作為 date 的值提供。

為了方便,基於日期的規則也可以使用流暢的 date 規則建構器來建立:

use Illuminate\Validation\Rule;

'start_date' => [
    'required',
    Rule::date()->before(today()->subDays(7)),
],

beforeTodaytodayOrBefore 方法可用於流暢地表達日期必須在今天之前,或今天或之前:

'start_date' => [
    'required',
    Rule::date()->beforeToday(),
],

before_or_equal:date

正在驗證的欄位必須是給定日期之前或等於的值。日期將被傳遞給 PHP strtotime 函數以轉換為有效的 DateTime 實例。此外,像 after 規則一樣,可以將另一個正在驗證的欄位名稱作為 date 的值提供。

為了方便,基於日期的規則也可以使用流暢的 date 規則建構器來建立:

use Illuminate\Validation\Rule;

'start_date' => [
    'required',
    Rule::date()->beforeOrEqual(today()->subDays(7)),
],

between:min,max

正在驗證的欄位必須具有在給定 minmax 之間的大小(包含)。字串、數值、陣列和檔案的評估方式與 size 規則相同。

boolean

正在驗證的欄位必須能夠被轉換為布林值。接受的輸入是 truefalse10"1""0"

您可以使用 strict 參數僅在值為 truefalse 時認為欄位有效:

'foo' => ['boolean:strict']

confirmed

正在驗證的欄位必須有一個匹配的 {field}_confirmation 欄位。例如,如果正在驗證的欄位是 password,則輸入中必須存在匹配的 password_confirmation 欄位。

您還可以傳遞自訂確認欄位名稱。例如,confirmed:repeat_username 將期望 repeat_username 欄位與正在驗證的欄位匹配。

contains:foo,bar,...

正在驗證的欄位必須是一個包含所有給定參數值的陣列。由於此規則通常需要您 implode 一個陣列,因此可以使用 Rule::contains 方法來流暢地建立規則:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'roles' => [
        'required',
        'array',
        Rule::contains(['admin', 'editor']),
    ],
]);

doesnt_contain:foo,bar,...

正在驗證的欄位必須是一個不包含任何給定參數值的陣列。由於此規則通常需要您 implode 一個陣列,因此可以使用 Rule::doesntContain 方法來流暢地建立規則:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'roles' => [
        'required',
        'array',
        Rule::doesntContain(['admin', 'editor']),
    ],
]);

current_password

正在驗證的欄位必須與已驗證使用者的密碼匹配。您可以使用規則的第一個參數指定身份驗證守衛

'password' => ['current_password:api']

date

正在驗證的欄位必須是根據 strtotime PHP 函數的有效、非相對日期。

date_equals:date

正在驗證的欄位必須等於給定的日期。日期將被傳遞給 PHP strtotime 函數以轉換為有效的 DateTime 實例。

date_format:format,...

正在驗證的欄位必須匹配給定的其中一種格式。驗證欄位時應使用 datedate_format,但不能同時使用兩者。此驗證規則支援 PHP 的 DateTime 類別支援的所有格式。

為了方便,基於日期的規則可以使用流暢的 date 規則建構器來建立:

use Illuminate\Validation\Rule;

'start_date' => [
    'required',
    Rule::date()->format('Y-m-d'),
],

decimal:min,max

正在驗證的欄位必須是數值的,並且必須包含指定的小數位數:

// 必須恰好有兩位小數(9.99)...
'price' => ['decimal:2']

// 必須有 2 到 4 位小數...
'price' => ['decimal:2,4']

declined

正在驗證的欄位必須是 "no""off"0"0"false"false"

declined_if:anotherfield,value,...

如果另一個正在驗證的欄位等於指定的值,則正在驗證的欄位必須是 "no""off"0"0"false"false"

different:field

正在驗證的欄位必須具有與 field 不同的值。

digits:value

正在驗證的整數必須具有 value 的確切長度。

digits_between:min,max

正在驗證的整數必須具有在給定 minmax 之間的長度。

dimensions

正在驗證的檔案必須是滿足規則參數指定的尺寸約束的圖片:

'avatar' => ['dimensions:min_width=100,min_height=200']

可用的約束有:min_widthmax_widthmin_heightmax_heightwidthheightratiomin_ratiomax_ratio

ratio 約束應表示為寬度除以高度。這可以透過像 3/2 這樣的分數或像 1.5 這樣的浮點數來指定:

'avatar' => ['dimensions:ratio=3/2']

min_ratiomax_ratio 約束可用於定義可接受的寬高比範圍:

'avatar' => ['dimensions:min_ratio=1/2,max_ratio=3/2']

由於此規則需要幾個參數,通常使用 Rule::dimensions 方法來流暢地建立規則更方便:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'avatar' => [
        'required',
        Rule::dimensions()
            ->maxWidth(1000)
            ->maxHeight(500)
            ->ratio(3 / 2),
    ],
]);

您還可以使用 minRatiomaxRatioratioBetween 方法來流暢地定義寬高比約束:

Rule::dimensions()->ratioBetween(min: 1 / 2, max: 3 / 2)

distinct

驗證陣列時,正在驗證的欄位不得有任何重複值:

'foo.*.id' => ['distinct']

預設情況下,distinct 使用鬆散的變數比較。要使用嚴格比較,您可以在驗證規則定義中添加 strict 參數:

'foo.*.id' => ['distinct:strict']

您可以向驗證規則的參數添加 ignore_case 以使規則忽略大小寫差異:

'foo.*.id' => ['distinct:ignore_case']

doesnt_start_with:foo,bar,...

正在驗證的欄位不得以給定的其中一個值開頭。

doesnt_end_with:foo,bar,...

正在驗證的欄位不得以給定的其中一個值結尾。

email

正在驗證的欄位必須格式化為電子郵件地址。此驗證規則使用 egulias/email-validator 套件來驗證電子郵件地址。預設情況下,應用了 RFCValidation 驗證器,但您也可以應用其他驗證樣式:

'email' => ['email:rfc,dns']

上面的範例將應用 RFCValidationDNSCheckValidation 驗證。以下是您可以應用的驗證樣式的完整列表:

  • rfcRFCValidation - 根據支援的 RFC 驗證電子郵件地址。
  • strictNoRFCWarningsValidation - 根據支援的 RFC 驗證電子郵件,當發現警告時失敗(例如尾隨句點和多個連續句點)。
  • dnsDNSCheckValidation - 確保電子郵件地址的網域具有有效的 MX 記錄。
  • spoofSpoofCheckValidation - 確保電子郵件地址不包含同形字或欺騙性 Unicode 字元。
  • filterFilterEmailValidation - 確保電子郵件地址根據 PHP 的 filter_var 函數有效。
  • filter_unicodeFilterEmailValidation::unicode() - 確保電子郵件地址根據 PHP 的 filter_var 函數有效,允許一些 Unicode 字元。

為了方便,可以使用流暢的規則建構器建立電子郵件驗證規則:

use Illuminate\Validation\Rule;

$request->validate([
    'email' => [
        'required',
        Rule::email()
            ->rfcCompliant(strict: false)
            ->validateMxRecord()
            ->preventSpoofing()
    ],
]);

[!WARNING] dnsspoof 驗證器需要 PHP intl 擴充套件。

encoding:encoding_type

正在驗證的欄位必須匹配指定的字元編碼。此規則使用 PHP 的 mb_check_encoding 函數來驗證給定檔案或字串值的編碼。為了方便,encoding 規則可以使用 Laravel 的流暢檔案規則建構器來建立:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;

Validator::validate($input, [
    'attachment' => [
        'required',
        File::types(['csv'])
            ->encoding('utf-8'),
    ],
]);

ends_with:foo,bar,...

正在驗證的欄位必須以給定的其中一個值結尾。

enum

Enum 規則是一個基於類別的規則,用於驗證正在驗證的欄位是否包含有效的列舉值。Enum 規則接受列舉的名稱作為其唯一的構造函數參數。驗證原始值時,應向 Enum 規則提供一個支援的列舉:

use App\Enums\ServerStatus;
use Illuminate\Validation\Rule;

$request->validate([
    'status' => [Rule::enum(ServerStatus::class)],
]);

Enum 規則的 onlyexcept 方法可用於限制哪些列舉案例應被視為有效:

Rule::enum(ServerStatus::class)
    ->only([ServerStatus::Pending, ServerStatus::Active]);

Rule::enum(ServerStatus::class)
    ->except([ServerStatus::Pending, ServerStatus::Active]);

when 方法可用於有條件地修改 Enum 規則:

use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

Rule::enum(ServerStatus::class)
    ->when(
        Auth::user()->isAdmin(),
        fn ($rule) => $rule->only(...),
        fn ($rule) => $rule->only(...),
    );

exclude

正在驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exclude_if:anotherfield,value

如果 anotherfield 欄位等於 value,則正在驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

如果需要複雜的有條件排除邏輯,您可以使用 Rule::excludeIf 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示是否應排除正在驗證的欄位:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::excludeIf($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::excludeIf(fn () => $request->user()->is_admin)],
]);

exclude_unless:anotherfield,value

除非 anotherfield 的欄位等於 value,否則正在驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。如果 valuenullexclude_unless:name,null),除非比較欄位為 null 或比較欄位不存在於請求資料中,否則正在驗證的欄位將被排除。

如果需要複雜的有條件排除邏輯,您可以使用 Rule::excludeUnless 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示是否不應排除正在驗證的欄位:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::excludeUnless($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::excludeUnless(fn () => $request->user()->is_admin)],
]);

exclude_with:anotherfield

如果 anotherfield 欄位存在,則正在驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exclude_without:anotherfield

如果 anotherfield 欄位不存在,則正在驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exists:table,column

正在驗證的欄位必須存在於給定的資料庫表中。

exists 規則的基本用法

'state' => ['exists:states']

如果未指定 column 選項,則將使用欄位名稱。因此,在此範例中,該規則將驗證 states 資料庫表是否包含一條 state 列值與請求的 state 屬性值匹配的記錄。

指定自訂欄位名稱

您可以透過在資料庫表名之後放置它來明確指定驗證規則應使用的資料庫欄位名稱:

'state' => ['exists:states,abbreviation']

有時,您可能需要指定用於 exists 查詢的特定資料庫連接。您可以透過在表名前面加上連接名稱來完成此操作:

'email' => ['exists:connection.staff,email']

不是直接指定表名,您可以指定應用於確定表名的 Eloquent 模型:

'user_id' => ['exists:App\Models\User,id']

如果您想自訂驗證規則執行的查詢,您可以使用 Rule 類別來流暢地定義規則。

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function (Builder $query) {
            $query->where('account_id', 1);
        }),
    ],
]);

您可以透過將欄位名稱作為 exists 方法的第二個參數提供,來明確指定 Rule::exists 方法生成的 exists 規則應使用的資料庫欄位名稱:

'state' => [Rule::exists('states', 'abbreviation')],

有時,您可能希望驗證值陣列是否存在於資料庫中。您可以透過向正在驗證的欄位同時添加 existsarray 規則來完成此操作:

'states' => ['array', Rule::exists('states', 'abbreviation')],

當這兩個規則都被分配給一個欄位時,Laravel 將自動建立一個單一查詢來判斷所有給定值是否存在于指定的表中。

extensions:foo,bar,...

正在驗證的檔案必須具有對應於列出的副檔名之一的使用者指定副檔名:

'photo' => ['required', 'extensions:jpg,png'],

[!WARNING] 您不應僅依賴按使用者指定的副檔名來驗證檔案。此規則通常應與 mimesmimetypes 規則結合使用。

file

正在驗證的欄位必須是成功上傳的檔案。

filled

正在驗證的欄位在存在時不得為空。

gt:field

正在驗證的欄位必須大於給定的 fieldvalue。這兩個欄位必須具有相同的類型。字串、數值、陣列和檔案使用與 size 規則相同的慣例進行評估。

gte:field

正在驗證的欄位必須大於或等於給定的 fieldvalue。這兩個欄位必須具有相同的類型。字串、數值、陣列和檔案使用與 size 規則相同的慣例進行評估。

hex_color

正在驗證的欄位必須包含十六進制格式的有效顏色值。

image

正在驗證的檔案必須是圖片(jpg、jpeg、png、bmp、gif 或 webp)。

[!WARNING] 預設情況下,image 規則不允許 SVG 檔案,因為可能存在 XSS 漏洞。如果您需要允許 SVG 檔案,您可以向 image 規則提供 allow_svg 指令(image:allow_svg)。

in:foo,bar,...

正在驗證的欄位必須包含在給定的值列表中。由於此規則通常需要您 implode 一個陣列,因此可以使用 Rule::in 方法來流暢地建立規則:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'zones' => [
        'required',
        Rule::in(['first-zone', 'second-zone']),
    ],
]);

in 規則與 array 規則結合時,輸入陣列中的每個值都必須存在於提供給 in 規則的值列表中。在以下範例中,輸入陣列中的 LAS 機場代碼是無效的,因為它不包含在提供給 in 規則的機場列表中:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$input = [
    'airports' => ['NYC', 'LAS'],
];

Validator::make($input, [
    'airports' => [
        'required',
        'array',
    ],
    'airports.*' => Rule::in(['NYC', 'LIT']),
]);

in_array:anotherfield.*

正在驗證的欄位必須存在於 anotherfield 的值中。

in_array_keys:value.*

正在驗證的欄位必須是一個陣列,該陣列中至少有一個給定的 values 作為金鑰:

'config' => ['array', 'in_array_keys:timezone']

integer

正在驗證的欄位必須是一個整數。

您可以使用 strict 參數僅在類型為 integer 時認為欄位有效。具有整數值的字串將被視為無效:

'age' => ['integer:strict']

[!WARNING] 此驗證規則不驗證輸入是否為「整數」變數類型,只驗證輸入是否為 PHP 的 FILTER_VALIDATE_INT 規則接受的類型。如果您需要驗證輸入為數字,請將此規則與numeric 驗證規則結合使用。

ip

正在驗證的欄位必須是一個 IP 地址。

ipv4

正在驗證的欄位必須是一個 IPv4 地址。

ipv6

正在驗證的欄位必須是一個 IPv6 地址。

json

正在驗證的欄位必須是一個有效的 JSON 字串。

lt:field

正在驗證的欄位必須小於給定的 field。這兩個欄位必須具有相同的類型。字串、數值、陣列和檔案使用與 size 規則相同的慣例進行評估。

lte:field

正在驗證的欄位必須小於或等於給定的 field。這兩個欄位必須具有相同的類型。字串、數值、陣列和檔案使用與 size 規則相同的慣例進行評估。

lowercase

正在驗證的欄位必須是小寫的。

list

正在驗證的欄位必須是一個列表陣列。如果陣列的金鑰由從 0 到 count($array) - 1 的連續數字組成,則認為該陣列是列表。

mac_address

正在驗證的欄位必須是一個 MAC 地址。

max:value

正在驗證的欄位必須小於或等於最大 value。字串、數值、陣列和檔案的評估方式與 size 規則相同。

max_digits:value

正在驗證的整數的最大長度必須為 value

mimetypes:text/plain,...

正在驗證的檔案必須匹配給定的 MIME 類型之一:

'video' => ['mimetypes:video/avi,video/mpeg,video/quicktime'],

'media' => ['mimetypes:image/*,video/*'],

要確定上傳檔案的 MIME 類型,將讀取檔案的內容,框架將嘗試猜測 MIME 類型,這可能與客戶端提供的 MIME 類型不同。

mimes:foo,bar,...

正在驗證的檔案必須具有對應於列出的副檔名之一的 MIME 類型:

'photo' => ['mimes:jpg,bmp,png']

即使您只需要指定副檔名,此規則實際上是透過讀取檔案的內容並猜測其 MIME 類型來驗證檔案的 MIME 類型。MIME 類型及其相應副檔名的完整列表可以在以下位置找到:

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

MIME 類型和副檔名

此驗證規則不驗證 MIME 類型與使用者分配給檔案的副檔名之間的一致性。例如,mimes:png 驗證規則將認為包含有效 PNG 內容的檔案是有效的 PNG 圖片,即使該檔案被命名為 photo.txt。如果您想驗證檔案的使用者指定副檔名,您可以使用 extensions 規則。

min:value

正在驗證的欄位必須具有最小 value。字串、數值、陣列和檔案的評估方式與 size 規則相同。

min_digits:value

正在驗證的整數的最小長度必須為 value

multiple_of:value

正在驗證的欄位必須是 value 的倍數。

missing

正在驗證的欄位不得存在於輸入資料中。

missing_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則正在驗證的欄位不得存在。

missing_unless:anotherfield,value

除非 anotherfield 欄位等於任何 value,否則正在驗證的欄位不得存在。

missing_with:foo,bar,...

正在驗證的欄位在任何其他指定欄位存在時不得存在。

missing_with_all:foo,bar,...

正在驗證的欄位在所有其他指定欄位都存在時不得存在。

not_in:foo,bar,...

正在驗證的欄位不得包含在給定的值列表中。Rule::notIn 方法可用於流暢地建立規則:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'toppings' => [
        'required',
        Rule::notIn(['sprinkles', 'cherries']),
    ],
]);

not_regex:pattern

正在驗證的欄位不得匹配給定的正規表達式。

在內部,此規則使用 PHP 的 preg_match 函數。指定的模式應遵循 preg_match 要求的相同格式,因此也應包含有效的分隔符。例如:'email' => ['not_regex:/^.+$/i']

nullable

正在驗證的欄位可以為 null

numeric

正在驗證的欄位必須是數值的

您可以使用 strict 參數僅在值為整數或浮點數類型時認為欄位有效。數字字串將被視為無效:

'amount' => ['numeric:strict']

present

正在驗證的欄位必須存在於輸入資料中。

present_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則正在驗證的欄位必須存在。

present_unless:anotherfield,value

除非 anotherfield 欄位等於任何 value,否則正在驗證的欄位必須存在。

present_with:foo,bar,...

正在驗證的欄位在任何其他指定欄位存在時必須存在。

present_with_all:foo,bar,...

正在驗證的欄位在所有其他指定欄位都存在時必須存在。

prohibited

正在驗證的欄位必須缺失或為空。如果滿足以下條件之一,則欄位為「空」:

  • 值為 null
  • 值為空字串。
  • 值為空陣列或空 Countable 物件。
  • 值為具有空路徑的上傳檔案。

prohibited_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則正在驗證的欄位必須缺失或為空。如果滿足以下條件之一,則欄位為「空」:

  • 值為 null
  • 值為空字串。
  • 值為空陣列或空 Countable 物件。
  • 值為具有空路徑的上傳檔案。

如果需要複雜的有條件禁止邏輯,您可以使用 Rule::prohibitedIf 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示是否應禁止正在驗證的欄位:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::prohibitedIf($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::prohibitedIf(fn () => $request->user()->is_admin)],
]);

prohibited_if_accepted:anotherfield,...

如果 anotherfield 欄位等於 "yes""on"1"1"true"true",則正在驗證的欄位必須缺失或為空。

prohibited_if_declined:anotherfield,...

如果 anotherfield 欄位等於 "no""off"0"0"false"false",則正在驗證的欄位必須缺失或為空。

prohibited_unless:anotherfield,value,...

除非 anotherfield 欄位等於任何 value,否則正在驗證的欄位必須缺失或為空。如果滿足以下條件之一,則欄位為「空」:

  • 值為 null
  • 值為空字串。
  • 值為空陣列或空 Countable 物件。
  • 值為具有空路徑的上傳檔案。

如果需要複雜的有條件禁止邏輯,您可以使用 Rule::prohibitedUnless 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示是否不應禁止正在驗證的欄位:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::prohibitedUnless($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::prohibitedUnless(fn () => $request->user()->is_admin)],
]);

prohibits:anotherfield,...

如果正在驗證的欄位不缺失或為空,則 anotherfield 中的所有欄位必須缺失或為空。如果滿足以下條件之一,則欄位為「空」:

  • 值為 null
  • 值為空字串。
  • 值為空陣列或空 Countable 物件。
  • 值為具有空路徑的上傳檔案。

regex:pattern

正在驗證的欄位必須匹配給定的正規表達式。

在內部,此規則使用 PHP 的 preg_match 函數。指定的模式應遵循 preg_match 要求的相同格式,因此也應包含有效的分隔符。例如:'email' => ['regex:/^.+@.+$/i']

required

正在驗證的欄位必須存在於輸入資料中且不為空。如果滿足以下條件之一,則欄位為「空」:

  • 值為 null
  • 值為空字串。
  • 值為空陣列或空 Countable 物件。
  • 值為沒有路徑的上傳檔案。

required_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則正在驗證的欄位必須存在且不為空。

如果您想為 required_if 規則建立更複雜的條件,您可以使用 Rule::requiredIf 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示正在驗證的欄位是否為必填:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::requiredIf($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::requiredIf(fn () => $request->user()->is_admin)],
]);

required_if_accepted:anotherfield,...

如果 anotherfield 欄位等於 "yes""on"1"1"true"true",則正在驗證的欄位必須存在且不為空。

required_if_declined:anotherfield,...

如果 anotherfield 欄位等於 "no""off"0"0"false"false",則正在驗證的欄位必須存在且不為空。

required_unless:anotherfield,value,...

除非 anotherfield 欄位等於任何 value,否則正在驗證的欄位必須存在且不為空。這也意味著 anotherfield 必須存在於請求資料中,除非 valuenull。如果 valuenullrequired_unless:name,null),除非比較欄位為 null 或比較欄位不存在於請求資料中,否則正在驗證的欄位將為必填。

如果您想為 required_unless 規則建立更複雜的條件,您可以使用 Rule::requiredUnless 方法。此方法接受一個布林值或一個閉包。給定閉包時,閉包應返回 truefalse 以指示正在驗證的欄位是否不為必填:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => [Rule::requiredUnless($request->user()->is_admin)],
]);

Validator::make($request->all(), [
    'role_id' => [Rule::requiredUnless(fn () => $request->user()->is_admin)],
]);

required_with:foo,bar,...

正在驗證的欄位在任何其他指定欄位存在且不為空時必須存在且不為空。

required_with_all:foo,bar,...

正在驗證的欄位在所有其他指定欄位都存在且不為空時必須存在且不為空。

required_without:foo,bar,...

正在驗證的欄位在任何其他指定欄位為空或不存在時必須存在且不為空。

required_without_all:foo,bar,...

正在驗證的欄位在所有其他指定欄位都為空或不存在時必須存在且不為空。

required_array_keys:foo,bar,...

正在驗證的欄位必須是一個陣列,並且必須包含至少指定的金鑰。

same:field

給定的 field 必須與正在驗證的欄位匹配。

size:value

正在驗證的欄位必須具有與給定 value 匹配的大小。對於字串資料,value 對應於字元數。對於數值資料,value 對應於給定的整數值(屬性還必須具有 numericinteger 規則)。對於陣列,size 對應於陣列的 count。對於檔案,size 對應於以千位元組為單位的檔案大小。讓我們看一些範例:

// 驗證字串恰好為 12 個字元長...
'title' => ['size:12'];

// 驗證提供的整數等於 10...
'seats' => ['integer', 'size:10'];

// 驗證陣列恰好有 5 個元素...
'tags' => ['array', 'size:5'];

// 驗證上傳的檔案恰好為 512 千位元組...
'image' => ['file', 'size:512'];

starts_with:foo,bar,...

正在驗證的欄位必須以給定的其中一個值開頭。

string

正在驗證的欄位必須是一個字串。如果您想允許欄位也為 null,則應將 nullable 規則分配給該欄位。

為了方便,字串驗證規則也可以使用流暢的 Rule::string() 規則建構器來建立:

use Illuminate\Validation\Rule;

'title' => [
    'required',
    Rule::string()
        ->min(3)
        ->max(255)
        ->alphaDash(ascii: true),
],

字串規則建構器提供了常見字串約束的方法,包括 alphaalphaDashalphaNumericasciibetweendoesntEndWithdoesntStartWithendsWithexactlylowercasemaxminstartsWithuppercase。由於規則建構器是可條件化的,您還可以使用 whenunless 方法來有條件地應用約束。

timezone

正在驗證的欄位必須是根據 DateTimeZone::listIdentifiers 方法的有效時區標識符。

DateTimeZone::listIdentifiers 方法接受的參數也可以提供給此驗證規則:

'timezone' => ['required', 'timezone:all'];

'timezone' => ['required', 'timezone:Africa'];

'timezone' => ['required', 'timezone:per_country,US'];

unique:table,column

正在驗證的欄位不得存在於給定的資料庫表中。

指定自訂表/欄位名稱:

不是直接指定表名,您可以指定應用於確定表名的 Eloquent 模型:

'email' => ['unique:App\Models\User,email_address']

column 選項可用於指定欄位的相應資料庫欄位。如果未指定 column 選項,則將使用正在驗證的欄位名稱。

'email' => ['unique:users,email_address']

指定自訂資料庫連接

有時,您可能需要為驗證器進行的資料庫查詢設定自訂連接。為此,您可以在表名前面加上連接名稱:

'email' => ['unique:connection.users,email_address']

強制唯一規則忽略給定 ID:

有時,您可能希望在唯一驗證期間忽略給定的 ID。例如,考慮一個包含使用者名、電子郵件地址和位置的「更新個人資料」畫面。您可能希望驗證電子郵件地址是唯一的。但是,如果使用者只更改了名稱欄位而沒有更改電子郵件欄位,則不希望因為使用者已經是該電子郵件地址的所有者而拋出驗證錯誤。

要指示驗證器忽略使用者的 ID,我們將使用 Rule 類別來流暢地定義規則。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

[!WARNING] 您不應將任何使用者控制的請求輸入傳遞給 ignore 方法。相反,您應該只傳遞系統生成的唯一 ID,例如自動遞增 ID 或來自 Eloquent 模型實例的 UUID。否則,您的應用程式將容易受到 SQL 注入攻擊。

不是將模型金鑰的值傳遞給 ignore 方法,您還可以傳遞整個模型實例。Laravel 將自動從模型中提取金鑰:

Rule::unique('users')->ignore($user)

如果您的表使用非 id 的主鍵列名,您可以在調用 ignore 方法時指定列名:

Rule::unique('users')->ignore($user->id, 'user_id')

預設情況下,unique 規則將檢查與正在驗證的屬性名稱匹配的列的唯一性。但是,您可以將不同的列名作為第二個參數傳遞給 unique 方法:

Rule::unique('users', 'email_address')->ignore($user->id)

添加額外的 Where 子句:

您可以透過使用 where 方法自訂查詢來指定額外的查詢條件。例如,讓我們添加一個查詢條件,將查詢範圍限制為僅搜索 account_id 列值為 1 的記錄:

'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))

在唯一性檢查中忽略已軟刪除的記錄:

預設情況下,唯一性規則在確定唯一性時包含已軟刪除的記錄。要從唯一性檢查中排除已軟刪除的記錄,您可以調用 withoutTrashed 方法:

Rule::unique('users')->withoutTrashed();

如果您的模型使用非 deleted_at 的列名來儲存已軟刪除的記錄,您可以在調用 withoutTrashed 方法時提供列名:

Rule::unique('users')->withoutTrashed('was_deleted_at');

uppercase

正在驗證的欄位必須是大寫的。

url

正在驗證的欄位必須是一個有效的 URL。

如果您想指定應被視為有效的 URL 協議,您可以將協議作為驗證規則參數傳遞:

'url' => ['url:http,https'],

'game' => ['url:minecraft,steam'],

ulid

正在驗證的欄位必須是一個有效的通用唯一字典排序可識別碼(ULID)。

uuid

正在驗證的欄位必須是一個有效的 RFC 9562(版本 1、3、4、5、6、7 或 8)通用唯一識別碼(UUID)。

您還可以驗證給定的 UUID 是否匹配特定版本的 UUID 規範:

'uuid' => ['uuid:4']

有條件地添加規則

當欄位具有某些值時跳過驗證

有時您可能希望在另一個欄位具有給定值時不驗證給定的欄位。您可以使用 exclude_if 驗證規則來完成此操作。在此範例中,如果 has_appointment 欄位的值為 false,則不會驗證 appointment_datedoctor_name 欄位:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($data, [
    'has_appointment' => ['required', 'boolean'],
    'appointment_date' => ['exclude_if:has_appointment,false', 'required', 'date'],
    'doctor_name' => ['exclude_if:has_appointment,false', 'required', 'string'],
]);

或者,您可以使用 exclude_unless 規則在另一個欄位不具有給定值時不驗證給定的欄位:

$validator = Validator::make($data, [
    'has_appointment' => ['required', 'boolean'],
    'appointment_date' => ['exclude_unless:has_appointment,true', 'required', 'date'],
    'doctor_name' => ['exclude_unless:has_appointment,true', 'required', 'string'],
]);

存在時驗證

在某些情況下,您可能希望在該欄位存在於正在驗證的資料中時才對該欄位執行驗證檢查。要快速完成此操作,請將 sometimes 規則添加到您的規則列表中:

$validator = Validator::make($data, [
    'email' => ['sometimes', 'required', 'email'],
]);

在上面的範例中,只有當 email 欄位存在於 $data 陣列中時,才會驗證該欄位。

[!NOTE] 如果您嘗試驗證一個應該始終存在但可能為空的欄位,請查看關於可選欄位的注意事項

複雜的有條件驗證

有時您可能希望根據更複雜的有條件邏輯添加驗證規則。例如,您可能希望僅在另一個欄位的值大於 100 時才要求給定的欄位。或者,您可能需要在另一個欄位存在時才需要兩個欄位具有給定的值。添加這些驗證規則不必是痛苦的。首先,使用您從不更改的靜態規則建立一個 Validator 實例:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'email' => ['required', 'email'],
    'games' => ['required', 'integer', 'min:0'],
]);

讓我們假設我們的 Web 應用程式是為遊戲收藏家服務的。如果一個遊戲收藏家在我們的應用程式中註冊並且他們擁有超過 100 個遊戲,我們希望他們解釋為什麼他們擁有這麼多遊戲。例如,也許他們經營一家遊戲轉售店,或者也許他們只是喜歡收集遊戲。為了有條件地添加此要求,我們可以使用 Validator 實例上的 sometimes 方法。

use Illuminate\Support\Fluent;

$validator->sometimes('reason', ['required', 'max:500'], function (Fluent $input) {
    return $input->games >= 100;
});

傳遞給 sometimes 方法的第一個參數是我們正在有條件驗證的欄位名稱。第二個參數是我們要添加的規則列表。如果作為第三個參數傳遞的閉包返回 true,則將添加規則。此方法使建立複雜的有條件驗證變得輕而易舉。您甚至可以一次為幾個欄位添加有條件驗證:

$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
    return $input->games >= 100;
});

[!NOTE] 傳遞給閉包的 $input 參數將是 Illuminate\Support\Fluent 的實例,可用於存取正在驗證的輸入和檔案。

複雜的有條件陣列驗證

有時您可能希望根據同一巢狀陣列中您不知道其索引的另一個欄位來驗證欄位。在這些情況下,您可以允許閉包接收第二個參數,該參數將是正在驗證的陣列中的當前單個項目:

$input = [
    'channels' => [
        [
            'type' => 'email',
            'address' => 'abigail@example.com',
        ],
        [
            'type' => 'url',
            'address' => 'https://example.com',
        ],
    ],
];

$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
    return $item->type === 'email';
});

$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
    return $item->type !== 'email';
});

像傳遞給閉包的 $input 參數一樣,當屬性資料是陣列時,$item 參數是 Illuminate\Support\Fluent 的實例;否則,它是一個字串。

驗證陣列

陣列驗證規則文檔中所述,array 規則接受允許的陣列金鑰列表。如果陣列中存在任何額外的金鑰,驗證將失敗:

use Illuminate\Support\Facades\Validator;

$input = [
    'user' => [
        'name' => 'Taylor Otwell',
        'username' => 'taylorotwell',
        'admin' => true,
    ],
];

Validator::make($input, [
    'user' => ['array:name,username'],
]);

通常,您應該始終指定允許存在於陣列中的陣列金鑰。否則,驗證器的 validatevalidated 方法將返回所有已驗證的資料,包括陣列及其所有金鑰,即使這些金鑰未被其他巢狀陣列驗證規則驗證。

驗證巢狀陣列輸入

驗證基於巢狀陣列的表單輸入欄位不必是痛苦的。您可以使用「點語法」來驗證陣列中的屬性。例如,如果傳入的 HTTP 請求包含 photos[profile] 欄位,您可以像這樣驗證它:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'photos.profile' => ['required', 'image'],
]);

您還可以驗證陣列的每個元素。例如,要驗證給定陣列輸入欄位中的每個電子郵件是否唯一,您可以執行以下操作:

$validator = Validator::make($request->all(), [
    'users.*.email' => ['email', 'unique:users'],
    'users.*.first_name' => ['required_with:users.*.last_name'],
]);

同樣,您可以在語言檔案中指定自訂驗證消息時使用 * 字元,這使得為基於陣列的欄位使用單個驗證消息變得輕而易舉:

'custom' => [
    'users.*.email' => [
        'unique' => '每個使用者必須有一個唯一的電子郵件地址',
    ]
],

存取巢狀陣列資料

有時您可能需要在向屬性分配驗證規則時存取給定巢狀陣列元素的值。您可以使用 Rule::forEach 方法來完成此操作。forEach 方法接受一個閉包,該閉包將在正在驗證的陣列屬性的每次迭代時被調用,並接收屬性的值和明確的、完全展開的屬性名稱。閉包應返回要分配給陣列元素的規則陣列:

use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$validator = Validator::make($request->all(), [
    'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
        return [
            Rule::exists(Company::class, 'id'),
            new HasPermission('manage-company', $value),
        ];
    }),
]);

錯誤消息索引和位置

驗證陣列時,您可能希望在應用程式顯示的錯誤消息中引用驗證失敗的特定項目的索引或位置。為此,您可以在自訂驗證消息中包含 :index(從 0 開始)、:position(從 1 開始)或 :ordinal-position(從 1st 開始)佔位符:

use Illuminate\Support\Facades\Validator;

$input = [
    'photos' => [
        [
            'name' => 'BeachVacation.jpg',
            'description' => '一張我海灘度假的照片!',
        ],
        [
            'name' => 'GrandCanyon.jpg',
            'description' => '',
        ],
    ],
];

Validator::validate($input, [
    'photos.*.description' => ['required'],
], [
    'photos.*.description.required' => '請描述照片 #:position。',
]);

給定上面的範例,驗證將失敗,使用者將看到以下錯誤:"請描述照片 #2。"

如有必要,您可以透過 second-indexsecond-positionthird-indexthird-position 等引用更深層巢狀的索引和位置。

'photos.*.attributes.*.string' => '照片 #:second-position 的屬性無效。',

驗證檔案

Laravel 提供了多種可用於驗證上傳檔案的驗證規則,例如 mimesimageminmax。雖然您可以自由地在驗證檔案時單獨指定這些規則,但 Laravel 還提供了一個流暢的檔案驗證規則建構器,您可能會發現它很方便:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;

Validator::validate($input, [
    'attachment' => [
        'required',
        File::types(['mp3', 'wav'])
            ->min(1024)
            ->max(12 * 1024),
    ],
]);

驗證檔案類型

即使您在調用 types 方法時只需要指定副檔名,此方法實際上是透過讀取檔案的內容並猜測其 MIME 類型來驗證檔案的 MIME 類型。MIME 類型及其相應副檔名的完整列表可以在以下位置找到:

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

驗證檔案大小

為了方便,最小和最大檔案大小可以指定為帶有指示檔案大小單位後綴的字串。支援 kbmbgbtb 後綴:

File::types(['mp3', 'wav'])
    ->min('1kb')
    ->max('10mb');

驗證圖片檔案

如果您的應用程式接受使用者上傳的圖片,您可以使用 File 規則的 image 構造函數方法來確保正在驗證的檔案是圖片(jpg、jpeg、png、bmp、gif 或 webp)。

此外,dimensions 規則可用於限制圖片的尺寸:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;

Validator::validate($input, [
    'photo' => [
        'required',
        File::image()
            ->min(1024)
            ->max(12 * 1024)
            ->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
    ],
]);

[!NOTE] 有關驗證圖片尺寸的更多資訊,請參閱尺寸規則文檔

[!WARNING] 預設情況下,image 規則不允許 SVG 檔案,因為可能存在 XSS 漏洞。如果您需要允許 SVG 檔案,您可以向 image 規則傳遞 allowSvg: trueFile::image(allowSvg: true)

驗證圖片尺寸

您還可以驗證圖片的尺寸。例如,要驗證上傳的圖片至少為 1000 像素寬和 500 像素高,您可以使用 dimensions 規則:

use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;

File::image()->dimensions(
    Rule::dimensions()
        ->maxWidth(1000)
        ->maxHeight(500)
)

[!NOTE] 有關驗證圖片尺寸的更多資訊,請參閱尺寸規則文檔

驗證密碼

為了確保密碼具有足夠的複雜度,您可以使用 Laravel 的 Password 規則物件:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;

$validator = Validator::make($request->all(), [
    'password' => ['required', 'confirmed', Password::min(8)],
]);

Password 規則物件允許您輕鬆自訂應用程式的密碼複雜度要求,例如指定密碼至少需要一個字母、數字、符號或混合大小寫的字元:

// 至少需要 8 個字元...
Password::min(8)

// 至少需要一個字母...
Password::min(8)->letters()

// 至少需要一個大寫和一個小寫字母...
Password::min(8)->mixedCase()

// 至少需要一個數字...
Password::min(8)->numbers()

// 至少需要一個符號...
Password::min(8)->symbols()

此外,您可以使用 uncompromised 方法確保密碼沒有在公開的密碼資料洩漏中被洩露:

Password::min(8)->uncompromised()

在內部,Password 規則物件使用 k-匿名性 模型透過 haveibeenpwned.com 服務來判斷密碼是否已被洩露,而不犧牲使用者的隱私或安全性。

預設情況下,如果密碼在資料洩漏中至少出現一次,則被視為已被洩露。您可以使用 uncompromised 方法的第一個參數來自訂此閾值:

// 確保密碼在同一資料洩漏中出現次數少於 3 次...
Password::min(8)->uncompramised(3);

當然,您可以鏈接上面範例中的所有方法:

Password::min(8)
    ->letters()
    ->mixedCase()
    ->numbers()
    ->symbols()
    ->uncompromised()

您可以使用 toPasswordRulesString 方法將 Password 規則物件轉換為適用於 HTML passwordrules 屬性的字串:

<input
    type="password"
    name="password"
    autocomplete="new-password"
    passwordrules="{{ Password::defaults()->toPasswordRulesString() }}"
/>

定義預設密碼規則

您可能會發現在應用程式的單個位置指定密碼的預設驗證規則很方便。您可以使用 Password::defaults 方法輕鬆完成此操作,該方法接受一個閉包。傳遞給 defaults 方法的閉包應返回 Password 規則的預設配置。通常,defaults 規則應在應用程式的其中一個服務提供者的 boot 方法中調用:

use Illuminate\Validation\Rules\Password;

/**
 * 引導任何應用程式服務。
 */
public function boot(): void
{
    Password::defaults(function () {
        $rule = Password::min(8);

        return $this->app->isProduction()
            ? $rule->mixedCase()->uncompromised()
            : $rule;
    });
}

然後,當您想將預設規則應用於正在驗證的特定密碼時,您可以不帶參數調用 defaults 方法:

'password' => ['required', Password::defaults()],

偶爾,您可能希望向預設密碼驗證規則附加額外的驗證規則。您可以使用 rules 方法來完成此操作:

use App\Rules\ZxcvbnRule;

Password::defaults(function () {
    $rule = Password::min(8)->rules([new ZxcvbnRule]);

    // ...
});

自訂驗證規則

使用規則物件

Laravel 提供了多種有用的驗證規則;但是,您可能希望指定一些自己的規則。註冊自訂驗證規則的一種方法是使用規則物件。要生成一個新的規則物件,您可以使用 make:rule Artisan 命令。讓我們使用此命令生成一個驗證字串是否為大寫的規則。Laravel 將把新規則放在 app/Rules 目錄中。如果此目錄不存在,當您執行 Artisan 命令建立規則時,Laravel 將建立它:

php artisan make:rule Uppercase

建立規則後,我們就準備好定義其行為了。規則物件包含一個方法:validate。此方法接收屬性名稱、其值以及一個在驗證失敗時應調用的回呼,並帶有驗證錯誤消息:

<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class Uppercase implements ValidationRule
{
    /**
     * 運行驗證規則。
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (strtoupper($value) !== $value) {
            $fail(':attribute 必須是大寫的。');
        }
    }
}

定義規則後,您可以透過將規則物件的實例與其他驗證規則一起傳遞來將其附加到驗證器:

use App\Rules\Uppercase;

$request->validate([
    'name' => ['required', 'string', new Uppercase],
]);

翻譯驗證消息

不是向 $fail 閉包提供文字錯誤消息,您還可以提供翻譯字串金鑰並指示 Laravel 翻譯錯誤消息:

if (strtoupper($value) !== $value) {
    $fail('validation.uppercase')->translate();
}

如有必要,您可以將佔位符替換和首選語言作為第一個和第二個參數傳遞給 translate 方法:

$fail('validation.location')->translate([
    'value' => $this->value,
], 'fr');

存取額外資料

如果您的自訂驗證規則類別需要存取所有其他正在驗證的資料,您的規則類別可以實現 Illuminate\Contracts\Validation\DataAwareRule 介面。此介面要求您的類別定義一個 setData 方法。此方法將在驗證開始之前由 Laravel 自動調用,並傳入所有正在驗證的資料:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;

class Uppercase implements DataAwareRule, ValidationRule
{
    /**
     * 所有正在驗證的資料。
     *
     * @var array<string, mixed>
     */
    protected $data = [];

    // ...

    /**
     * 設定正在驗證的資料。
     *
     * @param  array<string, mixed>  $data
     */
    public function setData(array $data): static
    {
        $this->data = $data;

        return $this;
    }
}

或者,如果您的驗證規則需要存取執行驗證的驗證器實例,您可以實現 ValidatorAwareRule 介面:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;

class Uppercase implements ValidationRule, ValidatorAwareRule
{
    /**
     * 驗證器實例。
     *
     * @var \Illuminate\Validation\Validator
     */
    protected $validator;

    // ...

    /**
     * 設定當前驗證器。
     */
    public function setValidator(Validator $validator): static
    {
        $this->validator = $validator;

        return $this;
    }
}

使用閉包

如果您只需要在應用程式中使用一次自訂規則的功能,您可以使用閉包而不是規則物件。閉包接收屬性的名稱、屬性的值以及一個 $fail 回呼,如果驗證失敗應調用該回呼:

use Illuminate\Support\Facades\Validator;
use Closure;

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function (string $attribute, mixed $value, Closure $fail) {
            if ($value === 'foo') {
                $fail("The {$attribute} is invalid.");
            }
        },
    ],
]);

隱式規則

預設情況下,當正在驗證的屬性不存在或包含空字串時,不會運行常規驗證規則,包括自訂規則。例如,unique 規則不會對空字串運行:

use Illuminate\Support\Facades\Validator;

$rules = ['name' => ['unique:users,name']];

$input = ['name' => ''];

Validator::make($input, $rules)->passes(); // true

對於即使在屬性為空時也要運行的自訂規則,該規則必須暗示該屬性是必填的。要快速生成一個新的隱式規則物件,您可以使用帶有 --implicit 選項的 make:rule Artisan 命令:

php artisan make:rule Uppercase --implicit

[!WARNING] 「隱式」規則只是暗示該屬性是必填的。它實際上是否使缺失或空的屬性無效取決於您。