Laravel4のEloquent ORMではまった件
掲題の件、めちゃめちゃはまりました。。
格闘すること数時間。
結果解決したのでホッとしているんですが、
備忘録と同じようなエラーではまっている人のために、
(そもそもはまる人がいるのかわかんないけど 笑)
ログとして残しておこうと思います。
やろうとしたこと
Eloquent ORMはLaravel4にデフォルトで含まれている。
コレを使うとModelとデータベース(のテーブル)を関連付けて、
簡単にデータ操作ができるようになります。
今回、ユーザーを管理するモデルとデータベースのテーブルとして以下をはじめに用意しました。
【Userモデル】
class User extends Eloquent { /** * モデルに関連付けるデータベースのテーブルを指定 * * @var string */ protected $table = 'users'; }
【usersテーブル】
mysql> desc users; +------------+------------------+------+-----+---------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+------------------+------+-----+---------------------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | email | varchar(255) | NO | UNI | NULL | | | login_name | varchar(255) | NO | | NULL | | | created_at | timestamp | NO | | 0000-00-00 00:00:00 | | | updated_at | timestamp | NO | | 0000-00-00 00:00:00 | | +------------+------------------+------+-----+---------------------+----------------+
※本当はパスワードとかその他もろもろ情報を付け足す予定でしたが、
まず最初の段階でがっつりつまづいたので、最低限のテーブル構造になってます。
■Laravel4 日本語ドキュメント - Eloquent ORM
http://laravel4.kore1server.com/docs/eloquent
この日本語ドキュメントの、
「基本的な使用法」
にもありますが、
一度モデルを定義したら、テーブルのレコードを取得したり、作成したりする準備は整います。
と書いてある!
「よっしゃー超簡単じゃーん♪」
と思ってしまったのがコトの発端です。。
早速新しいデータを追加してみよう!
と思った私は、
routes.phpに
Route::get('test', function() { $user = User::create(array('email' => 'test@test.com','login_name' => 'test',)); });
を追加して、/test にアクセスし、
新規データを追加しようと試みました。
が、
Illuminate \ Database \ Eloquent \ MassAssignmentException
ばっちりエラー画面が表示。。
なぜ・・
挿入するデータを替えてみたり、
データベースの文字コードを確認してみたり、
Eloquentクラスの中身を追ってデバッグしてみたり・・・
と色々試してみたんですが、どうにも解決せず。。
何がいけなかった?
■edongkoy | Tutorials: Laravel 4 MassAssignmentException Error
http://tutorials-edongkoy.blogspot.jp/2013/06/laravel-4-massassignmentexception-error.html
ようやく解決させてくれたのが上の記事でした。
Eloquent ORMを利用して、モデルとデータベースのテーブルを関連付け、
createメソッドでデータを挿入するためには、
protected $guarded = array('hogehoge');
もしくは
protected $fillable = array('hogahoga');
の設定が必ず必要!ということです。
要するに、今回のケースでいくと、
class User extends Eloquent { /** * モデルに関連付けるデータベースのテーブルを指定 * * @var string */ protected $table = 'users'; /** * createメソッド実行時に、入力を禁止するカラムの指定 * * @var array */ protected $guarded = array('id'); }
または
class User extends Eloquent { /** * モデルに関連付けるデータベースのテーブルを指定 * * @var string */ protected $table = 'users'; /** * createメソッド実行時に、入力を許可するカラムの指定 * * @var array */ protected $fillable = array('email','login_name'); }
と書く必要がありました。
てか、これぶっちゃけドキュメントに書いてあるんです。。笑
(ちゃんと読め!ってはなし)
もしくは一行で新しいモデルを保存するためにcreateメソッドを使用することも可能です。メソッドから挿入されたモデルのインスタンスがリターンされます。しかしながら全Eloquentモデルは複数代入から保護されているため、これを使用する前に操作対象のモデルに対しfillableかguardedプロパティのどちらかを指定しておく必要があります。
http://laravel4.kore1server.com/docs/eloquent#insert-update-delete
操作対象のモデルに対し、
※ fillableかguardedプロパティのどちらかを指定しておく必要があります。 ※
(これ重要。)
ということで、今回は
class User extends Eloquent { /** * モデルに関連付けるデータベースのテーブルを指定 * * @var string */ protected $table = 'users'; /** * createメソッド利用時に、入力を受け付けないカラムの指定 * * @var array */ protected $guarded = array('id'); // この行を追加。 }
とプログラムを修正することで、
ようやっと、迷宮から脱出することができましたとさ。。
今回の場合で上記のように設定したのは、
idのカラムはauto_incrementが設定されていて、
createメソッドでの入力に応じて値が変化する想定ではなかったので、
このような指定にしました。
でもさ・・・
一度モデルを定義したら、テーブルのレコードを取得したり、作成したりする準備は整います。
「作成する準備」は整ってないよね(>_<)