#php #laravel #laravel-8 #laravel-testing
Вопрос:
У меня есть a Trait
, который я использую на нескольких моделях в своем приложении для установки a UUID
на модели:
<?php
namespace AppTraits;
use IlluminateSupportStr;
trait UsesUuid
{
protected static function bootUsesUuid()
{
static::creating(function ($model) {
if (!$model->uuid) {
$model->uuid = (string) Str::orderedUuid();
}
});
}
}
Это нормально работает при обычном использовании приложения, но когда я пытаюсь написать тесты для создания модели с помощью a post
route
и дампа response
, я получаю Integrity constraint violation: 19 NOT NULL constraint failed: venues.uuid
500
ошибку.
Примером теста, который я провожу, является:
public function testOwnerCanSuccessfullyCreateVenue()
{
$amenity = Amenity::inRandomOrder()->pluck('id')->first();
$response = $this->actingAs($this->createdUser('owner'))->post(route('venues.store'), [
"name" => "create-name",
"address_line_1" => "create-address_line_1",
"address_line_2" => "create-address_line_2",
"county" => "create-county",
"postcode" => "create-postcode",
"phone_number" => "create-phone_number",
"notes" => "create-notes",
"amenities" => [$amenity]
]);
dd($response);
}
И колонка в моей миграции такова $table->uuid('uuid')->unique();
Все остальное работает блестяще, но я новичок в написании тестов и не знаю, как обойти эту проблему.
Причина, по которой я использовал признак, заключалась в том, чтобы обойти выделение всех значений столбцов при сохранении в базе данных, как я использую $request->validated()
для заполнения модели:
$venue = Venue::create($request->validated());
И, очевидно, из-за того, что UUID здесь не задается, это делается с помощью признака, который не прошел тест. Я могу пройти тест, и приложение все еще будет работать, если я удалю эту черту и сделаю это:
$venue = Venue::create(
$request->validated() ['uuid' => Str::orderedUuid()]
);
Что хорошо, я могу с этим смириться, но я хотел бы больше понять, почему эта Черта не стреляет и как ее обойти.
Изменить: Просто чтобы добавить больше, основываясь на приведенном ниже ответе, заполняемые поля определены правильно:
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'uuid',
'name',
'address_line_1',
'address_line_2',
'county',
'postcode',
'phone_number',
'notes',
];
Ответ №1:
Я думаю, что это проблема в модели. Venue
модель должна использовать protected $fillable = ['uuid'];
. По умолчанию Laravel защищает массовое назначение. В случае, если вы предоставляете массив при создании модели, Laravel этого не разрешает. Вам необходимо предоставить защищенный заполняемый массив, чтобы laravel мог разблокировать только эти поля.
Комментарии:
1. Если бы это было так, обходной путь не сработал бы, модель назначена правильно