How in factory to pass a parameter into configure method without field?

196 Views Asked by At

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 ?

0

There are 0 best solutions below