In laravel 8 app, fakerphp/faker: ^1.9, I am creating dummy data for a media table with different types of media (but I do not need a separate field for this). I have database/factories/NewsFactory.php:
<?php
class NewsFactory extends Factory
{
protected $model = News::class;
public function definition(): array
{
/// ...
// 4 different types of media are possible
$newsMediaType = $this->faker->randomElement([
'', /* no media */
'Y', /* youtube url */
'I', /* uploaded image */
'V', /* uploaded video */
]);
$youtubeUrl = '';
if($newsMediaType === 'Y') { // youtube url
$this->faker->addProvider(new \Faker\Provider\Youtube($this->faker));
$youtubeUrl = $this->faker->youtubeUri();
}
return [
// ...
'youtube_url' => $youtubeUrl, // "news" model has 'youtube_url' field - so I fill this fiels
'news_media_type' => $newsMediaType, // "news" model has NO 'news_media_type' field - I try to pass it as a parameter into afterCreating method
];
}
public function configure(): self
{
return $this->afterCreating(function (News $newNews) {
if ($newNews->news_media_type === 'I') {
$newNews->addMediaFromUrl('https://loremflickr.com/480/360')
->storingConversionsOnDisk('local')
->toMediaCollection('news_images');
}
});
}
But I got this error:
SQLSTATE[42703]: Undefined column: 7 ERROR: column "news_media_type" of relation "news" does not exist
LINE 1: ...t into "news" ("title", "content", "youtube_url", "news_medi...
^ (SQL: insert into "news" ("title", "content", "youtube_url", "news_media_type", "published_at", "created_at",
"updated_at") values (Test news Quo dolores laudantium illum., , , I, 2023-06-01 16:28:33, 2023-06-09 12:29:35,
2023-06-09 12:29:35) returning "id
I need somehow to pass news_media_type as a parameter into configure method.
Looking at https://laravel.com/docs/8.x/database-testing#factory-callbacks, I did not find such a possibility...
How can I do it?
UPDATED CLASS : I try to remake it with protected var :
<?php
namespace Database\Factories;
use App\Modules\News\Models\News;
use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory
{
protected $model = News::class;
protected $newsMediaType = null;
public function definition(): array
{
$this->newsMediaType = $this->faker->randomElement([''/* no media */, 'Y'/* youtube url */, 'I' /* uploaded image */, 'V'/* uploaded video */]);
$this->newsMediaType = 'I'; // FIXED VALUE FOR TESTING
\Log::info(' -10 $this->newsMediaType::');
\Log::info($this->newsMediaType);
$youtubeUrl = '';
if($this->newsMediaType === 'Y') { // youtube url
$this->faker->addProvider(new \Faker\Provider\Youtube($this->faker));
$youtubeUrl = $this->faker->youtubeUri();
}
return [
'youtube_url' => $youtubeUrl,
...
];
}
public function configure(): self
{
\Log::info( ' -12 $this->newsMediaType::');
\Log::info($this->newsMediaType);
return $this->afterCreating(function (News $newNews) {
\Log::info( ' -14 $this->newsMediaType::');
\Log::info($this->newsMediaType);
if ($this->newsMediaType === 'I') {
$newNews
->addMediaFromUrl('https://loremflickr.com/480/360')
->storingConversionsOnDisk('local')
->toMediaCollection('news_images');
}
});
}
}
and in log file I see :
[2023-06-10 06:10:50] local.INFO: -12 $this->newsMediaType::
[2023-06-10 06:10:50] local.INFO:
[2023-06-10 06:10:50] local.INFO: -10 $this->newsMediaType::
[2023-06-10 06:10:50] local.INFO: I
[2023-06-10 06:10:50] local.INFO: -14 $this->newsMediaType::
[2023-06-10 06:10:50] local.INFO:
So I see that firstly method configure() is called is called and $this->newsMediaType is empty.
Next method definition() is called and valid value is assigned to $this->newsMediaType. But next afterCreating() is called and $this->newsMediaType is not filled - it lost assigned priorly value ... What is wrong ?