如何将数组参数从播种器传递到工厂?

问题描述 投票:0回答:2

在 laravel 9 应用程序中,我需要使用带有经常重复 url 的工厂创建虚拟数据,以便在组中使用。所以在播种机中我有:

{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $itemsCount = 50;
        $faker = \Faker\Factory::create();
        $refUrls = [];

        for ($i = 0; $i < (int) ($itemsCount / 5); $i++) {
            $refUrls[] = $faker->url(); // I generate such array
        }

        BannerClickedCount::factory()
            ->count($itemsCount)
            ->create(['refUrls'=> $refUrls]);

并将其作为参数传递给工厂,但它不起作用,因为 BannerClickedCount 模型没有 refUrls 字段,我不能按传递方式使用它 参数到 database/factories/BannerClickedCountFactory.php:

class BannerClickedCountFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = BannerClickedCount::class;
    
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition($refUrls = []) // That is empty array
    {
        \Log::info(varDump($refUrls, ' -1 extends Factory $refUrls::'));
        ...

如何将数组参数从播种器传递到工厂?

附加代码: 我试图修改我的代码,但出现错误:

  current(): Argument #1 ($array) must be of type array, string given

  at database/seeders/banner_clicked_countsWithInitData.php:32
     28▕         }
     29▕         BannerClickedCount::factory()->count($itemsCount)
     30▕             ->state(new Sequence(
     31▕             // generate a sequence of reference URLs from the array
  ➜  32▕                 fn () => current($refUrls),
     33▕                 $refUrls
     34▕             ))
     35▕             ->create([]);
     36/* BannerClickedCount::factory()

  1   database/seeders/banner_clicked_countsWithInitData.php:32

附加代码#2:

$refUrls 在我的代码中是一个字符串数组:

$refUrls[] = $faker->url();

所以我认为我不需要使用爆炸,但我重新制作了种子文件:

$itemsCount = 10;
$faker           = \Faker\Factory::create();
$refUrls = [];
for($i = 0; $i< (int)($itemsCount/2) ; $i++) {
    $refUrls[] = $faker->url();
}
\Log::info(varDump($refUrls, ' -1 RUN Factory $refUrls::'));

BannerClickedCount::factory()->count($itemsCount)
    ->state(new Sequence(
        current($refUrls),
        $refUrls
    ))
    ->create([]); // Error pointing at this line !

我有错误:

  array_merge(): Argument #2 must be of type array, string given

  at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:438
    434             if ($state instanceof Closure) {
    435                 $state = $state->bindTo($this);
    436             }
    437 
   438             return array_merge($carry, $state($carry, $parent));
    439         }, $this->definition());
    440     }
    441 
    442     /**

      +8 vendor frames 
  9   [internal]:0
      Illuminate\Database\Eloquent\Factories\Factory::Illuminate\Database\Eloquent\Factories\{closure}()

      +2 vendor frames 
  12  database/seeders/banner_clicked_countsWithInitData.php:52
...

如何解决?

laravel faker
2个回答
1
投票

修改 BannerClickedCountFactory 类的定义方法以接受一个附加参数,该参数将接收引用 URL 数组。在您的播种机中,您可以将 $refUrls 数组传递给 BannerClickedCountFactory。

class BannerClickedCountFactory extends Factory
{
    // ...

    /**
     * Define the model's default state.
     *
     * @param array $refUrls
     * @return array
     */
    public function definition(array $refUrls = [])
    {
        return [
            // define the default state of your model
            'ref_url' => count($refUrls) > 0 ? array_shift($refUrls) : null,
            // other fields...
        ];
    }
}

播种机

BannerClickedCount::factory()
    ->count($itemsCount)
    ->state(new Sequence(
        // generate a sequence of reference URLs from the array
        fn () => current(explode(',', $refUrls)),
        $refUrls
    ))
    ->create();

0
投票

我通过在工厂中定义自定义方法 setRefUrl 解决了这个问题:

class BannerClickedCountFactory extends Factory
{
    protected $model = BannerClickedCount::class;

    public function definition($refUrls = [])
    {
        $locales = config('translatable.locales', []);
        return [
            'banner_id' => $this->faker->randomElement(Banner::all())['id'],
            'locale' => $this->faker->randomElement($locales),
            'user_id' => $this->faker->randomElement([1, 2, 3, 4, 5]),
            'ip'        => '127.0.0.1',
            'created_at' => $this->faker
                ->dateTimeBetween('-1 week', '-1 minute')
                ->format('Y-m-d G:i'),
        ];
    }
    public function setRefUrl($refUrls)
    {
        return $this->state(function (array $attributes) use($refUrls) {
            return [
                'ref_url' => $this->faker->randomElement($refUrls)
            ];
        });
    }

并在播种机中调用它:

$itemsCount = 200;
$faker           = \Faker\Factory::create();
$refUrls = [];
for($i = 0; $i< (int)($itemsCount/20) ; $i++) {
    $refUrls[] = $faker->url();
}
BannerClickedCount::factory()->count($itemsCount)->setRefUrl($refUrls)
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.