はじめに
MySQLでテストレコードを作るためにモデルをインスタンス化しました。
そして値を代入しようとしたところでタイトルにもあるGeneral errorエラーが出ました。
自分はモデルの$fillableプロパティを設定しなおすことで、エラーを解決することができました。
環境
Laravel Framework 9.52.16
MySQL 8.0.35
問題
> $user->messages()->create(['message' => 'エウルアたん3150', 'message_room_id' => 1]);
MySQLに接続して次のようにmessagesテーブルにテストレコードを作ろうとしていたところ…
> Illuminate\Database\QueryException SQLSTATE[HY000]: General error: 1364 Field 'message_room_id' doesn't have a default value (SQL: insert into messages (message, user_id, updated_at, created_at) values (エウルアたん3150, 3, 2023-12-19 00:00:00, 2023-12-19 00:00:00)).
このようなエラーが出ました。
「message_room_idはデフォルトの値を持ちません」という意味だと思いましたが、
「いや今しっかり代入したやんけ!(笑)」となっていました。
解決法
色々調べてみた所、Messageモデルに問題があったようです。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
use HasFactory;
protected $fillable = ['message'];
public function user()
{
return $this->belongsTo(User::class);
}
}
一括代入(mass assignment)を可能にする$fillableプロパティに漏れがあったようです。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
use HasFactory;
protected $fillable = ['message', 'message_room_id'];
public function user()
{
return $this->belongsTo(User::class);
}
}
$fillableプロパティにmessage_room_idを追加してあげることで、messageとの一括代入が可能となり、
無事にエラーが解決されました。
$fillableで悪意ある代入を防ぐ
Laravelの公式ドキュメントによれば、モデルに属性('message'など)を制限なしに一括代入できてしまう状態は、
悪意ある一括代入を招く危険性があるとされています。
具体例については、@monji586さんが丁寧に解説されている記事をご覧ください。
まとめ
> Illuminate\Database\QueryException SQLSTATE[HY000]: General error: 1364 Field 'message_room_id' doesn't have a default value (SQL: insert into messages (message, user_id, updated_at, created_at) values (エウルアたん3150, 3, 2023-12-19 00:00:00, 2023-12-19 00:00:00)).
エラー文だけでは該当箇所がどこか分かりにくい部分がありました。
しかし、今後一括代入する時はしっかりと$fillableプロパティをチェックします!!