ララベルのマニュアルで紹介されている一般的なDBレコードの作成方法は、

class Member extends Model
{
  protected $table = 'member';
  protected $primary_key = 'member_id';
  protected $timestamps = true;
}

use App\Models\Member;

$member = new Member();
$member->name = '山田太郎';
$member->email = 'tyamada@gmail.com';
$member->password = 'password'; // ここもちろん実際は暗号化して
$member->save();

Memberのインスタンスを作成し、ちまちまとそれぞれの項目を埋めて、最後にセーブ。

しかし、ウェブのアプリでは、コントローラーにおいて、ユーザーの入力がたくさんの項目でいっぺんに入ってくるので、

namespace App\Http\Controllers;

use App\Models\Member;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class SignupController extends Controller
{
  public function postSignup(Request $request)
  {
    $member = new Member;
    $member->fill($request->all())->save();
  }
}

と、先のようにひとつひとつの項目に値を割り当てずに、一気に保存することできます。いわゆる、一括割り当てのマスアサインメント(Mass Assignment)です。

しかし、このコード、ちょっと問題があります。

上のコードでは、フォームからポストされる項目名がすべてが、クラスMemberのDBテーブルにあると仮定して、ララベルは一括割り当てを試みます。

たとえば、以下のようなフォームでは、

    <form method="post" action="signup">
        ログイン:
        <input type="email" name="email" value="{{ old('email') }}" required autofocus>

        パスワード:
        <input type="password" name="password" required>

        パスワードの確認:
        <input type="password" name="password_confirmation" required>
        
        名前:
        <input type="text" name="name" value="{{ old('name') }}" required>

        <button type="submit">保存</button>

    </form>

以下の項目が入力項目名ですが、

email
password
password_confirmation
name

password_confirmationは、通常、パスワード確認のための入力項目でDBには存在しない項目です。その値をDBに入れようとするところでエラーとなります。

どうしましょう?

エロクエント(Eloquent)では、どの値をDBに入れてよいか、どれを入れていけないかのルールの設定が可能です。$fillableあるいは$guardedのどちらかの変数の定義がその目的で使用されます。前者は、ホワイトリスト(入力OKの項目のリスト)、後者はブラックリスト(入力禁止の項目のリスト)です。

class Product extends Model
{
  protected $table = 'member';
  protected $primary_key = 'member_id';
  protected $timestamps = true;

  protected $fillable = ['email', 'password', 'name'];
}

こうすれば、エラーがなくDBに値を無事に入れることができます。

$fillableの代わりに、以下でも良いですね。

protected $guarded = ['password_confirmation'];

By khino