【问题标题】:How can i seed with faker a random id or null in Laravel?我如何在 Laravel 中用 faker 播种随机 id 或 null ?
【发布时间】:2019-01-17 23:54:40
【问题描述】:

我正在尝试使用同一个表的随机 id 为 parent_id 列播种,或者让它为空。

我认为它会起作用:

...
'parent_id' => $faker->boolean() ? Page::all()->random()->id : null,
...

但我收到以下错误:

  You requested 1 items, but there are only 0 items available. 

有人知道怎么做吗?

更新1:

使用伪动画答案我尝试了流动:

$factory->define(Page::class, function (Faker\Generator $faker) {
...
    $parent_id = null;
...
    $has_parent = $faker->boolean(50);
    Log::debug('$has_parent' . $has_parent);
    if ($has_parent) {
        $parents = Page::all();
        Log::debug('$parents' . count($parents));

        if ($parents->isEmpty()) {
            Log::debug('isEmpty');

            $parent_id = null;
        } else {
            Log::debug('$parents->random()' . print_r($parents->random(), true));
            $parent_id = $parents->random()->id;
        }
    }

    return [
...

        'parent_id' => $parent_id,
...
    ];
}

从我每次运行时看到的Page::all(); 返回空。 知道这是为什么吗?

【问题讨论】:

  • Page::all() 返回 0 个结果,所以不能随机选择 1 个
  • 我知道这是错误的原因,但我如何生成随机的 parent_id 否则?
  • 首先创建(播种)页面以供选择?
  • 这是一个很好的问题。不应该被否决。如果您有一个可选的表单字段 - 很常见! - 它可能会填充用户 ID 或项目 ID,或者它可能为空。

标签: laravel laravel-5 seeding faker


【解决方案1】:

试试这个:

'parent_id' => $faker->boolean(50) ? Page::orderByRaw('RAND()')->first()->id : null,

基本上我们是说,随机排序,获取第一个,然后获取它的 id。

boolean(50) 应该给你 50% 的机会是真的,所以是 50% 的假。

【讨论】:

  • SQLSTATE[42883]: Undefined function: 7 ERROR: function rand() does not exist LINE 1: select * from "pages" order by RAND() limit 1
  • 试试orderByRaw我有orderbyRaw
  • 我也试过$faker->boolean(50) ? Page::inRandomOrder()->get()->first()->id : null,,但我得到Trying to get property 'id' of non-object
【解决方案2】:
$factory->define(Page::class, function (Faker\Generator $faker) {
    $ids = Page::pluck('id')->toArray();

    return [
        'parent_id' = empty($ids) ? null : $faker->optional(0.9, null)->randomElement($ids);  // 10% chance of null
    ];
});

【讨论】:

【解决方案3】:

您的错误正在发生,因为您对页面 (page:all()->random()) 的查询没有返回任何结果。

基本上,您的问题是您关心在创建页面之前尝试为页面创建父级。

您可以尝试检查 Page::all() 是否返回非空集合,如果是,则从那里获取一个随机元素,如果不是,则创建一个新元素。

我个人会做一些事情,比如为 null 父元素创建一个类,以及为 null 和非空父元素创建一个类。

$factory->defineAs(Page::class, 'ParentPage', function (Faker $faker) {
    return [
        //the rest of your elements here
        'parent_id' => null
    ];
});

$factory->defineAs(Page::class, 'page', function (Faker $faker) {
    $has_parent = $faker->boolean();
    if($has_parent) {
        $parents = Page::all();
        if($parents->isEmpty()) {
            $parent_id = factory(Page::class, 'ParentPage')->create()->id;
        } else {
            $parent_id = $parents->random()->id;
        }
    }
    return [
        //the rest of your elements here
        'parent_id' => $has_parent? $parent_id : null
    ];
});

您可以在播种器中创建像factory(Page::class, 'page')->times(50)->create(); 这样的常规页面

上面的代码没有经过测试,但逻辑应该是正确的。

【讨论】:

  • 从你的代码开始我这样测试它:` $parent_id = null; $has_parent = $faker->boolean(); if ($has_parent) { $parents = Page::all(); if (!$parents->isEmpty()) { $parent_id = Page::all()->random()->id; } } return [ 'parent_id' => $parent_id,]` 但是虽然它运行没有错误,但它不会生成任何 parent_id。
  • 我刚刚在我的机器上尝试了代码,它正在为我生成 parent_ids,我已经更新了代码以匹配我的确切代码,你现在可以试试吗?
  • @vlad,你还没有改变函数参数,你需要定义两个模型工厂函数并将函数签名更新为 $factory->defineAs(Page::class, 'ParentPage', function (Faker $faker) 和 $factory->defineAs(Page::class, 'page', function (Faker $faker) 分别。请再次查看我的答案。
【解决方案4】:
public function run()
    {
        factory(\App\Comment::class, 30)->make()->each(function ($comment){
            $comments = Comment::all();
            if ($comments->count() == 0) {
                $comment->parent = null;
            } else {
                $rand = random_int(1, $comments->count());
                if ($rand >= 2 && $rand <= 5){
                    $comment->parent = null;
                }elseif ($rand >= 12 && $rand <=17){
                    $comment->parent = null;
                }elseif ($rand >= 22 && $rand <= 27){
                    $comment->parent = null;
                }else{
                    $comment->parent = $rand;
                }
            }
            $comment->save();
        });
    }

【讨论】:

    【解决方案5】:

    将“Parent”作为父模型,我这样做:

    1. 首先播种父母;
    2. 在工厂中使用此代码为子表播种:

    'parent_id' =&gt; $faker-&gt;optional()-&gt;randomElement(App\Parent::all()-&gt;pluck('id'))

    之所以有效,是因为faker 的 randomElement() 采用了一个数组,您在该数组中填充了所有且仅填充父表的 'id' 值。

    optional() 伪造者的修饰符随机在 parent_id 中放置或不放置 NULL。正如faker's GitHub 中所述,optional() 有时会绕过提供程序以返回默认值(默认为 NULL)。 也可以指定接收到默认值的概率和返回的默认值。

    注意:如果父表未播种,您将无法执行任何操作。如果是这样,请考虑dlnsk的答案。

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 1970-01-01
      • 2018-09-03
      • 2018-05-26
      • 2018-09-10
      • 2017-10-02
      • 1970-01-01
      • 2018-09-03
      • 2017-08-29
      相关资源
      最近更新 更多