当模型有构造函数时,Laravel 工厂失败

Posted

技术标签:

【中文标题】当模型有构造函数时,Laravel 工厂失败【英文标题】:Laravel factory fails when the model has a constructor 【发布时间】:2021-12-27 19:32:12 【问题描述】:

在 Laravel 8 中,当我在具有 __construct 的模型上运行 factory()->create() 时,此代码:

Route::get('/test', function ()
    $doc = ClientDocument::factory()->create();
);

失败:

"SQLSTATE[HY000]: General error: 1364 Field 'filename' doesn't have a default value (SQL: insert into `client_documents` (`updated_at`, `created_at`) values (2021-11-16 12:45:20, 2021-11-16 12:45:20))"

如果我删除 __construct,工厂运行正常并保存到数据库中......我在这里缺少什么?谢谢!

型号

class ClientDocument extends Model

    use HasFactory;

    protected $connection = 'mysql';

    protected $fillable = ['filename'];
    protected $locale;

    public function __construct() 
        // SET THE LANGUAGE
        if ( auth()->user() ) 
             $this->locale = auth()->user()->locale;
         else 
             $this->locale = 'en';
        
    

工厂

class ClientDocumentFactory extends Factory

    public function definition()
    
        $user = User::factory()->create();
        $client = $user->createNewClientFile();

        return [
            'filename'  => $this->faker->lexify('????????'),
        ];
    

迁移

class CreateClientDocumentsTable extends Migration

    public function up()
    
        Schema::create('client_documents', function (Blueprint $table) 
            $table->id();
            $table->string('filename');
            $table->timestamps();
        );

    

    public function down()
    
        Schema::dropIfExists('client_documents');
    

【问题讨论】:

Welcome to SO ... 模型已经定义了一个构造函数,它实际上做了一些事情,你只是覆盖了这个构造函数而不做任何事情(如果你定义了一个不做'不获取属性并填充模型?)...github.com/laravel/framework/blob/8.x/src/Illuminate/Database/… 你至少需要调用父构造函数,否则你的构造函数是空的,因此没用 无论我添加 parent::__construct() 还是 __construct 中的任何其他代码都不会改变任何东西,同样的错误。为了简单起见,我删除了代码……但也许我不应该这样做! ;) 我已经编辑了我的答案以使其更清晰 不仅仅是调用父构造函数。基类 Model 的构造函数签名为 public function __construct(array $attributes = []),因此您应该使构造函数与该签名兼容,并将可选的 $attributes 传递给父类 谢谢布赖恩·汤普森(和其他人)。我知道是这样的,只是找不到。谢谢大家。 【参考方案1】:

为了结束这个问题,我将 Brian Thompson 的答案写在 cmets 中:

“这不仅仅是调用父构造函数。基础模型类具有公共函数__construct(array $attributes = [])的构造函数签名,因此您应该使您的构造函数与该签名兼容并传递可选的$父属性"

所以基本上,我只是将我的构造函数代码更改为:

public function __construct(array $attributes = []) 
    parent::__construct($attributes);
   

【讨论】:

以上是关于当模型有构造函数时,Laravel 工厂失败的主要内容,如果未能解决你的问题,请参考以下文章

C++ 静态工厂构造函数

Jackson 因“无法构造 WorkpoolId 的实例(尽管至少存在一个 Creator)而失败:没有 int/Int-argument 构造函数/工厂”

当网络边缘的构造函数抛出时避免 SIGTRAP

2.工厂模式==》对象

objectmapper.readValue() 失败并出现错误“没有从字符串值反序列化的字符串参数构造函数/工厂方法”

面向对象2