在 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
...
如何解决?
修改 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();
我通过在工厂中定义自定义方法 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)