日記
前の会社をやめて一年が経ってしまった。
起きたこと
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
@param
@return
public function __construct(array $attributes = [])
{
$this->bootIfNotBooted();
$this->syncOriginal();;
$this->fill($attributes);
}
create()
でProductのインスタンスをつくるという基本的なことを忘れていて、attributes
って、tinkerでnewしたときに設定してないよな、、、どっからくるんだ、と思ってました。
そもそもModelクラス内にもトレイトにもcreateメソッドはないんだけれども、どう呼んでるんだろうという新たな謎を胸に秘め生きていこうと思います。