Laravelのnullableとは、対象のフィールドが「NULL(空)を許可する」ことを指定する仕組みです。ポイントは、同じnullableという言葉でもデータベース(Migration)とバリデーション(Validation)で役割が異なることです。
- Migrationのnullable:DBのカラム定義で、その列にNULLを保存できるようにする(テーブル構造の話)
- Validationのnullable:フォーム入力の検証で、値が空でもエラーにしない(入力チェックの話)
本記事では、この2つのnullableを混同しないように、それぞれの基本コードと実務での使い方、関連ルール(required / sometimes / present)との違いまで整理します。目的の箇所からすぐに読めるよう、以下のリンクを用意しました。
- nullableとは(DBとValidationで役割が異なる)
- Migrationでのnullableの使い方
- Validationでのnullableの使い方
- nullable / required / sometimes / present の違い(比較表)
nullable属性とは
Laravelにおけるnullableとは、「NULL値(何も値がない状態)を許可する」ための識別子です。データベースのマイグレーションとバリデーションの両方で使われますが、扱う対象が異なります。
「null値」とは、文字列・数値・日付などの具体的な値ではなく、「何も設定されていない(未知・存在しない)」ことを表す特別な値です。nullableを指定すると、そのフィールドは具体的な値の代わりにnullを保持できるようになり、「アパート番号のように入力が任意な項目」などを正確に表現できます。
DBのnullableとValidationのnullableは別物
初心者がつまずきやすいのが、この2つは独立しているという点です。
- DBカラムを
nullable()にしても、Validationでrequiredにすれば空入力はエラーになる - 逆にValidationを
nullableにしても、DB側がNOT NULL(nullable()未指定)ならnull保存時にSQLエラーになる
つまり「空を許可したい項目」は、DB(Migration)とValidationの両方でnullableを揃えるのが基本です。以降でそれぞれの書き方を見ていきます。
nullable属性を使うメリット
- データの正確性の向上:無効なデータやダミー値を避け、「存在しない/未知」をnullで正確に表現できる
- 柔軟なデータモデリング:必須ではない項目にnullableを設定でき、将来の拡張にも対応しやすい
- バリデーションの柔軟性:任意項目を「空ならスキップ、入力があれば検証」と柔軟に制御できる
ただしnull値の扱いには注意が必要です。null前提のコードでnullチェックを怠ると、実行時にNull Pointer的なエラー(Attempt to read property on nullなど)を招くことがあります。nullを許可する項目では、参照側でも常にnullの可能性を考慮してください。
Migrationでのnullableの使い方
まずはデータベース側です。Laravelのマイグレーションでは、カラム定義に->nullable()をチェーンするだけで、その列にNULLを保存できるようになります。
新しいカラムをnullableで追加する基本例
もっとも基本的な形が$table->string('name')->nullable()です。以下はusersテーブルに、null許容のemailとbirthdateを追加する例です。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
// 文字列カラムをnull許容で追加する基本形
$table->string('name')->nullable();
$table->string('email')->nullable();
// 日付カラムもnull許容にできる
$table->date('birthdate')->nullable();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['name', 'email', 'birthdate']);
});
}
};
->nullable()を付けない場合、そのカラムはNOT NULL制約になり、null(値なし)で保存しようとするとデータベースエラーになります。「入力が任意な項目」にはnullable()を付けるのが基本です。マイグレーション自体のコマンド操作はPHP artisanコマンド活用法の記事で詳しく解説しています。
既存カラムをnullableに変更する場合
すでにあるカラムを後からnull許容へ変える場合は、->change()を使います。以下は、NOT NULLだったphoneカラムをnull許容に変更する例です。
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
// 既存カラムをnull許容へ変更する
$table->string('phone')->nullable()->change();
});
}
変更時の注意点は次のとおりです。
- 元の型を省略しない:
change()は既存定義を上書きするため、string('phone')のように型・長さも含めて再指定します。nullable()だけを付け直そうとすると型が意図せず変わることがあります。 - Laravel 10以降はdoctrine/dbal不要:Laravel 9以前で
change()を使うにはdoctrine/dbalパッケージが必要でしたが、Laravel 10以降は標準でchange()が使えます(利用中のバージョンはLaravelバージョン確認の記事で確認できます)。 - NOT NULL → nullableは安全、逆は注意:null許容へ緩める方向は既存データを壊しませんが、nullableをNOT NULLへ戻す場合は、既存のnullレコードがあると変更に失敗します。事前にnullをデフォルト値で埋める必要があります。
ロールバック(down)も忘れずに、変更前の状態へ戻す処理を書いておきましょう。スキーマ変更を伴う設計変更の例は主キーをULIDに変更する記事も参考になります。
Validationでのnullableの使い方
次に入力チェック側です。フォームリクエストのバリデーションでnullableルールを指定すると、その項目が空(null)ならエラーにせず通し、値がある場合だけ他のルールを適用できます。
nullableルールの基本例
配列形式で書くと、'field' => ['nullable', 'string']のようになります。以下は任意項目を含むバリデーション例です。
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users'],
// 空ならスキップ、入力があれば数値として検証
'phone' => ['nullable', 'numeric'],
// 空ならスキップ、入力があれば日付として検証
'birthdate' => ['nullable', 'date'],
]);
phoneやbirthdateは、未入力(null)ならそのまま通過し、値が入っていればnumeric / dateのルールで検証されます。nullableを付けないと、Laravelは「入力があるべき」と解釈し、空でも型ルールでエラーになることがあるため、任意項目には明示的に付けるのが安全です。より発展的な検証はLaravelバリデーションをマスターする記事で解説しています。
nullable / required / sometimes / present の違い
nullableは似たルールと混同されがちです。「キーの有無」と「空を許すか」の2軸で整理すると分かりやすくなります。
| ルール | 意味 | 空(null)を許可 | キー自体が無い場合 |
|---|---|---|---|
nullable | 値がnullでも許可し、他ルールをスキップ | 許可する | 他ルール次第 |
required | 必須。null・空文字・空配列を拒否 | 拒否する | エラー |
sometimes | キーが存在する時だけ他ルールを適用 | —(存在時のみ検証) | 検証しない(許可) |
present | キーの存在は必須。値は空でもよい | 許可する | エラー |
- nullable vs required:任意なら
nullable、必須ならrequired。真逆の関係です。 - nullable vs present:
presentは「キーは必ず送ること。ただし中身は空でも可」。フォームで項目自体の送信を保証したい時に使います。 - nullable vs sometimes:
sometimesは「キーが無ければ検証しない」。部分更新(PATCH)で送られた項目だけ検証したい時に便利です。['sometimes', 'nullable', 'string']のように組み合わせられます。
空文字がnullへ変換されるケースに注意
LaravelにはConvertEmptyStringsToNullというミドルウェアが標準で有効になっており、リクエストの空文字("")は自動的にnullへ変換されます。HTMLフォームの未入力テキストは空文字で送られるため、実際にはnullとしてバリデーションに渡ります。
この挙動を知らないと、次のような食い違いが起きます。
- フォームで空欄のまま送信 → 空文字 → nullに変換 →
nullableならOK、requiredならエラー - DB側が
nullable()なら空欄はnullで保存される。DBがNOT NULLだと、空文字ではなくnullが渡るため保存エラーになる
「空文字で保存されるはず」と思っていた項目がnullになるのはこのためです。Validationとカラム定義(NOT NULL / nullable)を揃えておけば、この食い違いは防げます。
実務でのnullable利用例
実際の開発では、次のような任意項目でnullableが役立ちます。いずれも「Migrationでnullable()」「Validationでnullable」をセットで揃えるのが基本です。
- フォーム入力(任意項目):ミドルネーム、電話番号、備考欄など。例:
['nullable', 'string', 'max:255'] - 日付:退会日、公開予定日など未定になり得る項目。例:
['nullable', 'date']。DB側は$table->date('published_at')->nullable() - 数値:割引率や在庫上限など未設定を許す項目。例:
['nullable', 'integer', 'min:0'] - 外部キー:「担当者未割り当て」など関連が任意なケース。例:
$table->foreignId('user_id')->nullable()->constrained()とし、Validationは['nullable', 'exists:users,id']
特に外部キーをnullableにする場合は、リレーション先を参照するコードでnullチェックを入れておくと、担当者未割り当てのレコードでもエラーになりません。
まとめ
Laravelのnullableは、DB(Migration)とValidationの両方で「空を許可する」ための仕組みですが、扱う対象が異なる別々の設定です。
- Migration:
$table->string('name')->nullable()でカラムにNULLを許可。既存カラムは->change()で変更できる。 - Validation:
'field' => ['nullable', 'string']で空入力を許可。required/sometimes/presentとの違いを押さえる。 - 空文字→null変換:
ConvertEmptyStringsToNullにより空欄はnull扱い。DBとValidationのnullable設定を揃えて食い違いを防ぐ。
「空を許可したい項目」は、MigrationとValidationの両方でnullableを揃える——これを意識するだけで、保存エラーや意図しないバリデーション失敗の多くを防げます。
関連記事
- Laravelバリデーションをマスターする:基礎から上級テクニックまで
- PHP artisan | Laravel開発の基本とコマンド活用法(migrate操作)
- Laravelで主キーをULIDに変更する方法と利点(スキーマ変更)

コメントを残す