Home > other >  Refractoring Laravel 7 Factory to Laravel 8
Refractoring Laravel 7 Factory to Laravel 8

Time:10-30

I am having a hard to figuring out how to refractor a factory in Laravel 7 to Laravel 8. Below is the original factory in L7 and the L8 version below is the one I've tried refactoring. I know the $factory->define is wrong and this is where I am stuck.

Laravel 7 Version

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Login;
use Faker\Generator as Faker;

$factory->define(Login::class, function (Faker $faker) {
    $randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');
    return [
        'user_id' => factory(App\User::class),
        'tenant_id' => factory(App\Tenant::class),
        'created_at' => $randomDateTime,
        'updated_at' => $randomDateTime,
    ];
});

Laravel 8 Version

<?php

namespace Database\Factories;

use App\Models\Login;
use App\Models\Tenant;
use App\Models\User;
use Faker\Generator as Faker;


$factory->define(Login::class, function (Faker $faker) {
    $randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');
    return [
        'user_id' => User::factory(),
        'tenant_id' => Tenant::factory(),
        'created_at' => $randomDateTime,
        'updated_at' => $randomDateTime,
    ];
});

CodePudding user response:

You have two options here:

Use old factories

If you don't have the time for properly refactoring your factories, you can still use your old Laravel 7 factories by pulling in the laravel/legacy-factories package:

composer require laravel/legacy-factories

Refactor your factories

Laravel 8 factories are now classes. Previously, you would call a define method on the $factory object, passing it the class and a closure that would return the factory definition like so:

<?php

use App\User;
use Faker\Generator as Faker;
use Illuminate\Support\Str;

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
        'remember_token' => Str::random(10),
    ];
});

In Laravel 8, the same would be written as follows and be put in database/factories/UserFactory.php for auto-discovery:

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
            'remember_token' => Str::random(10),
        ];
    }
}

As you see, factories are now separate classes that extend from the Illuminate\Database\Eloquent\Factories\Factory class.

Additionally, you need to use the Illuminate\Database\Eloquent\Factories\HasFactory trait on the Model to allow the discovery of factories for the Model. Once you add this trait, Laravel expects a Factory class by the name of the Model, suffixed with Factory in the database/factories folder.

You can read up on all that in the Defining Model Factories chapter of the database testing documentation.

In your specific case

The code you posted would need to be refactored and put in database/factories/LoginFactory.php:

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class LoginFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        $randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');

        return [
            'user_id' => User::factory(),
            'tenant_id' => Tenant::factory(),
            'created_at' => $randomDateTime,
            'updated_at' => $randomDateTime,
        ];
    }
}

Then you need to use Illuminate\Database\Eloquent\Factories\HasFactory; in your Login.php model class and of course you would have do the same for the User and Tenant models, creating UserFactory.php and TenantFactory.php.

  • Related