Ad

Laravel Factory Using Custom Create Method

- 1 answer

I'm overriding the create method on a few of my models, like in this question. The problem I'm finding is that factories for these models fail because they aren't calling my custom create method.

Model code:

class Teacher extends Model {
  public static function create(array $attributes)
  {
    $user = User::create(['name' => $attributes['name']);
    return static::query()->create(['budget' => $attributes['budget', 'user_id' => $user->id]);
  }

Factory code:

$factory->define(App\Teacher::class, function(Faker $faker) {
  return [
    'name' => $faker->firstName(),
    'budget' => $faker->numberBetween(100, 1000)
  ];
}

I get the following error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'name' in 'field list' (SQL: insert into `teachers` (`name`, `budget`, `updated_at`, `created_at`) values (Audreanne, 600, 2020-04-07 16:43:54, 2020-04-07 16:43:54))

Any help is greatly appreciated!

Ad

Answer

Answer

Factories do not use the model create method to create the model it uses the save method. You should change your factory to be like the below:

$factory->define(App\Teacher::class, function(Faker $faker) {
  return [
    'user_id' => function () {
        return factory(App\User::class)->create()->id;
    },
    'budget' => $faker->numberBetween(100, 1000)
  ];
});

You should have a UserFactory.php already that will generate a name for the associated user.

Additional Advice

As for overriding the create function on your model I strongly do not recommend this approach.

And where you are creating your teacher in code I would recommend taking this approach:

// For example in TeacherController::store
$budget = 500;
$user_id = User::create(['name' => 'Peter Griffin'])->id;
$teacher = Teacher::create(compact('budget', 'user_id'));

If you find that you are needing to do this code in multiple places then I would suggest implementing a new method on your model (see below) or create a service class to handle it:

class Teacher extends Model {
    public static function createWithUser($name, $budget): Teacher
    {
        $user_id = User::create(compact('name'))->id;
        return Teacher::create(compact('budget', 'user_id'));          
    }
}

// For example
$teacher = Teacher::createWithUser('Peter Griffin', 500);
Ad
source: stackoverflow.com
Ad