与 Laravel faker 的嵌套关系 - laravel 播种机

Posted

技术标签:

【中文标题】与 Laravel faker 的嵌套关系 - laravel 播种机【英文标题】:Nested relationships with Laravel faker - laravel seeder 【发布时间】:2018-05-26 07:16:49 【问题描述】:

如 laravel 文档 https://laravel.com/docs/5.5/database-testing 中的关系部分所述,我想与用户和 cmets 一起创建一个 post seeder

  $users = factory(App\User::class, 3)
     ->create()
     ->each(function ($u) 
          $u->posts()->save(factory(App\Post::class)
            ->create()
            ->each(function($p)
                $p->comments()->save(factory(App\Comment::class,5)
                  ->create()
                  ->each(function($c)
                      $c->user()->save(factory(App\User::class)
                        ->make()
                      );
                  )
                );
              )
            );
        
    );

预期的输出是让 3 个用户的帖子每人有 5 个 cmets。

但是发生了错误:

在 Builder.php 第 2459 行:调用未定义的方法 Illuminate\Database\Query\Builder::save()

【问题讨论】:

【参考方案1】:

试试这个:

$users = factory(App\User::class, 3)
     ->create()
     ->each(function ($u) 
          $u->posts()->save(factory(App\Post::class)->make())
            ->each(function($p)
                $p->comments()->save(factory(App\Comment::class,5)->make())
                  ->each(function($c)
                      $c->user()->save(factory(App\User::class)
                        ->make()
                      );
                  )
                );
              )
            );
        
    );

使用常规 foreach 的解决方案

$users = factory(App\User::class, 3)->create();

foreach($users as $user)
    $post = $user->posts()
                          ->create(factory(App\Post::class)->make()->toArray());
    $post->comments()
                     ->createMany(
                               factory(App\Comment::class, 5)
                      ->make(['user_id' => factory(App\User::class)
                               ->create()->id])->toArray());

【讨论】:

呃,我刚刚编辑了你的代码,问题是你试图在工厂创建的模型上使用 save() 方法。我认为使用常规 foreach 会不那么复杂 我正在编辑我的解决方案,可能无法正常工作,因为我无法立即对其进行测试,但您可以大致了解 :) 您的解决方案不起作用..但我知道我做错了什么..谢谢..在您的解决方案中,我们必须在创建方法中使用数组..不是吗.. 哈哈是的!确实 !它只是缺少 ->toArray() 吗?我编辑了我的答案,但如果你有一个可行的解决方案,你也可以编辑它:) 上面的代码显示完整性约束违规:1062 Duplicate entry '1' for key 'PRIMARY' ..【参考方案2】:

例如,您的解决方案中有几个问题

$p->comments()->save(factory(App\Comment::class,5)

您正在尝试使用 save() 保存多个 cmets,这将导致错误,您应该使用 saveMany() 代替。 但是,您的问题的解决方案可能是这样的:

$users = factory(App\User::class, 3)->create()
        ->each(function ($user) 
            $user->posts()->saveMany(factory(App\Post::class, 5)->make());
        );
foreach ($users as $user)
  foreach ($user->posts as $post)
    $post->comments()->saveMany(factory(App\Comment::class, 5)->make());
  

这将按预期工作。

【讨论】:

【参考方案3】:

试试这个方法:

        $users = factory(App\User::class, 5)->create();

    foreach ($users as $user) 
        $articles = factory(App\Article::class, 5)->create([
            'user_id' => $user->id
        ]);

        foreach ($articles as $article) 
            factory(App\Comment::class, 5)->create([
                'article_id' => $article['id']
            ]);
        
    

【讨论】:

以上是关于与 Laravel faker 的嵌套关系 - laravel 播种机的主要内容,如果未能解决你的问题,请参考以下文章

laravel 关联模型 多态关系

Laravel Eloquent 嵌套关系枢轴与约束

如何在 Laravel 中加载嵌套关系

如何在Laravel中加载嵌套关系

带有嵌套关系的 Laravel 急切加载

laravel faker数据填充详解