In laravel 9 app I need to create dummy data with factory with aften repeating url for using in groups. So in seeder I have :
{
/**
* 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]);
and pass it to factory as parameter, but it does not work as BannerClickedCount model has no refUrls field and I can not use it as passed parameter into 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::'));
...
How can I pass array parameter from seeder into Factory ?
ADDTIVE CODE : I tried to modify my code, but got error :
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
ADDTIVE CODE # 2:
$refUrls in my code is an array of strings :
$refUrls[] = $faker->url();
So I think I do not need explode be used, but with I remade seeder file :
$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 !
I got error :
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
...
How to fix it ?
I salved the isue with defining custom method setRefUrl in factory :
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)
];
});
}
and calling it in the seeder :
$itemsCount = 200;
$faker = \Faker\Factory::create();
$refUrls = [];
for($i = 0; $i< (int)($itemsCount/20) ; $i++) {
$refUrls[] = $faker->url();
}
BannerClickedCount::factory()->count($itemsCount)->setRefUrl($refUrls)