豆腐とコンソメ

豆腐とコンソメ

もろもろのプログラム勉強記録

LaravelのModelのcreateでハマった件

日記

前の会社をやめて一年が経ってしまった。

起きたこと

Laravelなんとなく使えるようになったかなと思ったけれども、未だにフレームワークがちゃんと読めない。
というかPHPの基本的なところがわかってないんじゃないか疑惑。

こんな平凡なProductモデルがあって、

Productモデル

<?php
namespace App;

class Product extends Models
{
   $fillable = ['product_id'];

    public function __construct() {
        parent::__construct();
        //以降に個別の設定処理
    }
}   

tinkerでProductレコードを新規に作成するメソッド`create()'を実行したら、エラーになった。

実行した処理

$ php artisan tinker
Psy Shell v0.8.12 (PHP 7.1.11 ― cli) by Justin Hileman
>>> $product = new App\Product
>>> $product->create(['product_id' => 1]);

エラーメッセージに表示されているSQLをみると、create()の引数に指定している、product_idが無視されているではありませんか。

エラーメッセージ

Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1364 Field 'product_id' doesn't have a default value (SQL: insert into `products` (`updated_at`, `created_at`) values (2018-07-02 15:52:14, 2018-07-02 15:52:14))'


あれ、モデルにfillableもちゃんと書いてるよな、、、と1時間ぐらいハマってたんですが、 原因はコンストラクタでした。

stackoverflow.com

以下にようにモデルのコンストラクタに、arrtibutesの引数を設定してあげます。

修正後のProductモデル

<?php
namespace App;

class Product extends Models
{
   $fillable = ['product_id'];

    public function __construct(array $attributes = []) {
        parent::__construct($attributes);
        //以降に個別の設定処理
    }
}   

フレームワーク内のModel.phpのコンストラクタをみると、attributesの引数があり、これはcreate()で渡している配列の値っぽいです。

Model.php

<?php

    /**
     * Create a new Eloquent model instance.
     *
     * @param  array  $attributes
     * @return void
     */
    public function __construct(array $attributes = [])
    {
        $this->bootIfNotBooted();

        $this->syncOriginal();;

        $this->fill($attributes);
    }

create()でProductのインスタンスをつくるという基本的なことを忘れていて、attributesって、tinkerでnewしたときに設定してないよな、、、どっからくるんだ、と思ってました。

そもそもModelクラス内にもトレイトにもcreateメソッドはないんだけれども、どう呼んでるんだろうという新たな謎を胸に秘め生きていこうと思います。