0

我的问题

我最近开始使用 Laravel 8。我正在尝试使用播种机和工厂生成测试数据。但是我总是遇到错误,而且 Laravel 8 的文档对我来说太差了。如果有人可以帮助我解决我的问题,我将不胜感激。

我的代码

用户工厂

<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'firstname' => $this->faker->name(),
            'lastname' => $this->faker->name(),

            "birthdate" => $this->faker->date(),
            "birthplace" => $this->faker->city(),

            'email' => $this->faker->unique()->freeEmail(),
            'password' => $this->faker->password(),
        ];
    }

    /**
     * Indicate that the model's email address should be unverified.
     *
     * @return \Illuminate\Database\Eloquent\Factories\Factory
     */
    public function unverified()
    {
        return $this->state(function (array $attributes) {
            return [
                'email_verified_at' => null,
            ];
        });
    }
}

用户邮箱工厂

<?php

namespace Database\Factories;

use App\Models\UserEmail;
use Illuminate\Database\Eloquent\Factories\Factory;

class UserEmailFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = UserEmail::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            "name" => $this->faker->words(1),
            "email" => $this->faker->unique()->freeEmail(),
        ];
    }
}

用户模型

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * Tablename
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * PrimaryKey
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'firstname',
        'lastname',
        'birthdate',
        'birthplace',
        'taxnumber',
        'email',
        'password'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password'
    ];

    /**
     * Relation: One User has many UserEmails
     */
    public function useremails() {
        $this->hasMany(UserEmail::class);
    }
    
    /**
     * Relation: One User has many UserPasswords
     */
    public function userpasswords() {
        $this->hasMany(UserPassword::class);
    }
    
    /**
     * Relation: One User has many UserPhones
     */
    public function userphones() {
        $this->hasMany(UserPhone::class);
    }
}

用户电子邮件模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class UserEmail extends Model
{
    use HasFactory;

    /**
     * Tablename
     *
     * @var string
     */
    protected $table = 'user_emails';

    /**
     * PrimaryKey
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'user_id',
        'name',
        'email'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
    ];


    /**
     * Relation: One UserEmail belongs to a User
     */
    public function user() {
        return $this->belongsTo(User::class);
    }
}

我的测试

UserSeeder 测试 1

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

use App\Models\User;
use App\Models\UserEmail;
use App\Models\UserPassword;
use App\Models\UserPhone;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        for ($i = 0; $i < 100; $i++) {
            $user = User::factory()->create();
            
            $userEmail = UserEmail::factory()
                ->count(5)
                ->state(
                    function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    }
                )
                ->create();
            $userPassword = UserPassword::factory()
                ->count(5)
                ->state(
                    function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    }
                )
                ->create();
            $userPhone = UserPhone::factory()
                ->count(5)
                ->state(
                    function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    }
                )
                ->create();
        }
    }
}
Database\Seeders\UserSeeder::Database\Seeders\{closure}(): Argument #2 ($user) must be of type App\Models\User, null given

UserSeeder 测试 2

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

use App\Models\User;
use App\Models\UserEmail;
use App\Models\UserPassword;
use App\Models\UserPhone;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        $user = User::factory()
            ->has(
                UserEmail::factory()
                    ->count(5)
                    ->state(function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    })
                    ->create()
            )
            ->has(
                UserPassword::factory()
                    ->count(5)
                    ->state(function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    })
                    ->create()
            )
            ->has(
                UserPhone::factory()
                    ->count(5)
                    ->state(function (array $attributes, User $user) {
                        return ['user_id' => $user->id];
                    })
                    ->create()
            )            
            ->create();
    }
}
Database\Seeders\UserSeeder::Database\Seeders\{closure}(): Argument #2 ($user) must be of type App\Models\User, null given
4

1 回答 1

0

(Note: I haven't tested the code below)

In your UserFactory, I'd define states with methods called emails(), phones(), and passwords(). Here's an example of emails():

 /**
 * Add emails to this user account
 *
 * @return \Illuminate\Database\Eloquent\Factories\Factory
 */
public function emails(int $count)
{
    return $this->afterCreating(function (User $user) use ($count) {
        for ($i = 0; $i < $count; $i++) {
            $user->useremails()->create([
                    'email' => $this->faker->safeEmail,
            ]);
        }

    });
}

Then, when you need to create the User, you can run:

public function run()
{
    \App\Models\User::factory()
                ->count(5)
                ->emails(5)
                ->create();
}

and it will create 5 users, with 5 email addresses each. As a bonus, in the emails() state method you can update the $user record so that the "email" column in the User table matches one of your UserEmail records.

If you wanted to create a User with 5 email address, and 2 phone numbers, you could call:

public function run()
{
    \App\Models\User::factory()
                ->count(5)
                ->emails(5)
                ->phones(2)
                ->create();
}
于 2021-05-16T14:38:26.840 回答