1

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!

2
  • The budget column does not appear to exist in your teachers table are you sure you have migrated it? Commented Apr 7, 2020 at 18:10
  • @Purgatory Ahh I made a mistake. I've edited the error. Commented Apr 7, 2020 at 18:55

1 Answer 1

3

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the insight. I agree, overriding Model methods does seem a bit messy. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.