| この記事の要点 |
|---|
|
マスアサインメント保護
Laravel の User::create($request->all()) のように配列を一括代入する操作(マスアサインメント)は、攻撃者が任意のフィールドを送り込める脆弱性があります。$fillable / $guarded でこれを制御します。
$fillable(ホワイトリスト・推奨)
class User extends Model
{
protected $fillable = [
'name',
'email',
'phone',
];
// role や is_admin は含まれない → 一括代入できない
}
// 使用
User::create([
'name' => 'Alice',
'email' => 'alice@example.com',
'role' => 'admin', // ← 無視される (fillable にないので)
]);
User::create($request->all());
// → name, email, phone のみセットされる、他は無視
$guarded(ブラックリスト)
class User extends Model
{
// 'id', 'role' は一括代入禁止
protected $guarded = ['id', 'role', 'is_admin'];
}
// 空配列で全許可 (危険、テスト用)
protected $guarded = [];
// ガード解除 (デバッグ用、本番禁止)
Model::unguard();
$fillable と $guarded はどちらか一方
$fillable推奨: 許可するものを明示するほうが安全$guarded: 多くを許可する場合、禁止するものだけ列挙- 両方使うと
$fillableが優先
マスアサインメントが効くメソッド・効かないメソッド
| メソッド | マスアサインメント保護 |
|---|---|
Model::create($attrs) | ○ |
$model->fill($attrs) | ○ |
$model->update($attrs) | ○ |
$model->save() | ×(直接代入は OK) |
$model->forceFill($attrs) | ×(強制代入) |
Model::forceCreate($attrs) | × |
個別代入 $model->name = ... | × |
// 個別代入は OK
$user = new User();
$user->name = "Alice";
$user->role = "admin"; // ← fillable に関係なくセットできる
$user->save();
// forceFill / forceCreate は意図的に保護をバイパス
$user = User::forceCreate([
'name' => 'Admin',
'role' => 'admin',
'is_admin' => true
]);
$hidden(JSON シリアライゼーション)
toArray() / toJson() 時に含めない属性:
class User extends Model
{
protected $hidden = [
'password',
'remember_token',
'api_secret',
];
}
// 使用
$user = User::find(1);
return $user->toJson();
// → {"id":1, "name":"Alice", "email":"..."}
// password は含まれない
return $user; // 自動的に JSON 化される (Resource Controller)
// → 同上、password 非表示
$visible(逆: 表示するもののホワイトリスト)
class User extends Model
{
protected $visible = ['id', 'name', 'email'];
// → これら以外は全て隠す
}
// $hidden と $visible は併用可、$hidden が優先
動的に変更
// 一時的に表示 / 非表示
$user = User::find(1);
$user->makeVisible('password'); // password を表示
$user->makeHidden(['name', 'email']); // 一時的に隠す
return $user->toJson();
その他の関連プロパティ
$casts(型変換)
class User extends Model
{
protected $casts = [
'is_admin' => 'boolean',
'options' => 'array', // JSON カラム → 配列に
'birthday' => 'date',
'last_login_at' => 'datetime',
'price' => 'decimal:2',
];
}
// 利用
$user->is_admin // → bool
$user->options // → array (DB は JSON 文字列)
$user->birthday // → Carbon インスタンス
$dates(廃止予定、$casts に統合)
// 古い書き方 (Laravel 6 以前)
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
// 新しい書き方 (Laravel 7+)
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
$appends(カスタム属性をシリアライズに含める)
class User extends Model
{
protected $appends = ['full_name'];
public function getFullNameAttribute()
{
return $this->first_name . ' ' . $this->last_name;
}
}
// toJson() の結果
// {
// "id": 1,
// "first_name": "Alice",
// "last_name": "Smith",
// "full_name": "Alice Smith" ← appends で追加
// }
標準的なモデル例
class User extends Authenticatable
{
use HasFactory, Notifiable;
// 一括代入を許可するフィールド
protected $fillable = [
'name',
'email',
'password',
];
// シリアライゼーションから除外
protected $hidden = [
'password',
'remember_token',
];
// 型変換
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed', // 自動でハッシュ化
];
// 追加属性
protected $appends = ['avatar_url'];
public function getAvatarUrlAttribute()
{
return $this->avatar
? Storage::url($this->avatar)
: asset('img/default-avatar.png');
}
}
セキュリティ上の注意
- $fillable の指定なしは MassAssignmentException 発生 (Laravel 5.5+)
- $guarded = [] は危険、絶対使わない(本番では)
- パスワード等の機密情報は必ず $hidden に
- API レスポンス用には API Resources を使うほうが柔軟
API Resources(より柔軟)
// 専用のリソースクラス
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->toIso8601String(),
// フロント側に必要な情報だけ厳選
];
}
}
// コントローラから
return new UserResource($user);
return UserResource::collection($users);
関連記事
子ページ
子ページはありません
同階層のページ
- モデルの作成
- $fillable $guarded $hiddenの説明
- テーブルの紐づけ
- 主キーの指定とインクリメント
- タイムスタンプ
- モデルでselect
- モデルでinsert
- モデルでupdate
- 現在値に加算する方法
- created_at/updated_atの別名指定
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38