Laravel:使用工厂具有多个属于关系的种子表

Loo*_*oon 2 php laravel eloquent

长话短说:

我正在使用 Laravel 和 Eloquent 并尝试为数据库添加种子并将多个所属关系附加到一个表,但出现错误:

调用未定义的方法 Illuminate\Database\Eloquent\Relations\BelongsTo::attach()

详细解释:

我正在使用php 7.1andLaravel 6与 Eloquent 一起使用。我正在尝试播种测试数据库。我有以下关系结构:

一个用户有多个帖子/一个帖子属于一个用户

一个类别有多个帖子/一个帖子属于一个类别

用户模型:

class User extends Model
{
    protected $table = 'users';

    public function posts()
    {
        return $this->hasMany('App\Models\Post');
    }
} 
Run Code Online (Sandbox Code Playgroud)

类别型号:

class Category extends Model
{
    protected $table = 'categories';

    public function posts()
    {
        return $this->hasMany('App\Models\Category');
    }
}
Run Code Online (Sandbox Code Playgroud)

帖子型号:

class Post extends Model
{
    protected $table = 'posts';

    public function category()
    {
        return $this->belongsTo('App\Models\Category');
    }

    public function user()
    {
        return $this->belongsTo('App\Models\User');
    }
}
Run Code Online (Sandbox Code Playgroud)

用户工厂:

$factory->define(User::class, function (Faker $faker) {
    return [
        'id' => $faker->unique()->randomNumber(3),
        'name' => $faker->name(),
    ];
});
Run Code Online (Sandbox Code Playgroud)

工厂类别:

$factory->define(Category::class, function (Faker $faker) {
    return [
        'id' => $faker->unique()->randomNumber(3),
        'name' => $faker->word(),
    ];
});
Run Code Online (Sandbox Code Playgroud)

邮厂:

$factory->define(User::class, function (Faker $faker) {
    return [
        'id' => $faker->unique()->randomNumber(3),
        'name' => $faker->realText($maxNbChars = 200, $indexSize = 2),
    ];
});
Run Code Online (Sandbox Code Playgroud)

如果我只有用户和帖子,我知道我可以通过以下方式为数据库播种:

public function seed()
{
    $users = factory(App\User::class, 10)
        ->create()
        ->each(function ($user) {
            $user->posts()->createMany(factory(App\Post::class, 10)->make()->toArray());
        });
}
Run Code Online (Sandbox Code Playgroud)

但显然这对我来说不起作用。我已经尝试过以下方法:

public function seed()
{
    factory(User::class, 10)->create();
    factory(Category::class, 10)->create();
    factory(Post::class, 100)->create()->each(function ($post){
        $post->user()->attach(User::all()->random(1));
        $post->category()->attach(Category::all()->random(1));
    });
}
Run Code Online (Sandbox Code Playgroud)

以及使用 make/save 而不是 create 的相同功能:

public function seed()
    {
        factory(User::class, 10)->create();
        factory(Category::class, 10)->create();
        factory(Post::class, 100)->make()->each(function ($post) {
            $post->user()->attach(User::all()->random(1));
            $post->category()->attach(Category::all()->random(1));
        })->save();
    }
Run Code Online (Sandbox Code Playgroud)

但在这两种情况下,我都会收到错误:

调用未定义的方法 Illuminate\Database\Eloquent\Relations\BelongsTo::attach()

Rem*_*mul 6

你必须使用associate()

public function seed()
{
    factory(User::class, 10)->create();
    factory(Category::class, 10)->create();
    factory(Post::class, 100)->make()->each(function ($post) {
        $post->user()->associate(User::inRandomOrder()->first());
        $post->category()->associate(Category::inRandomOrder()->first());
        $post->save();
    });
}
Run Code Online (Sandbox Code Playgroud)

还将User::all()->random(1)返回一个集合而不是模型,这将引发异常,我将其替换为Model::inRandomOrder()->first(),这将从数据库中获取随机模型。

来自文档

更新belongsTo关系时,可以使用associate方法。此方法将在子模型上设置外键:

$account = App\Account::find(10);

$user->account()->associate($account);

$user->save();
Run Code Online (Sandbox Code Playgroud)

更新

在你的模型工厂中:

/** @var Factory $factory */
$factory->define(Post::class, function (Faker\Generator $faker) {
    return [
        // not sure why you do this, is it not a autoincrement column?
        'id' => $faker->unique()->randomNumber(3), 
        'name' => $faker->realText($maxNbChars = 200, $indexSize = 2),
        'category_id' => function () {
            if ($category = Category::inRandomOrder()->first()) {
                return $category->id;
            }

            return factory(Category::class)->create()->id;
        },
        'user_id' => function () {
            if ($user = User::inRandomOrder()->first()) {
                return $user->id;
            }

            return factory(User::class)->create()->id;
        },
    ];
});
Run Code Online (Sandbox Code Playgroud)

在你的播种机中:

public function seed()
{
    factory(User::class, 10)->create();
    factory(Category::class, 10)->create();
    factory(Post::class, 100)->create();
}
Run Code Online (Sandbox Code Playgroud)