Framework: Extending/Overloading Model::create no longer works

Created on 10 Feb 2017  路  5Comments  路  Source: laravel/framework

  • Laravel Version: 5.4.9
  • PHP Version: 7.1.0
  • Database Driver & Version: 5.7.16-0ubuntu0.16.04.1

Description:

When you override an Eloquent Model with public static function create and have it call parent::create, you are getting a never ending loop because it sends it to line 1326 __callStatic which instantiates a new version of the Model and calls create on it. Because the create method was removed from Model, this just calls your create method again.

It appears that the create method was moved to the Builder class (I can't see any documentation in any release notes) and this causes a breaking change when upgrading to 5.4. Is there a new way to do this?

Steps To Reproduce:

  1. Create a new trait that overrides public static function create()
  2. Make sure your create uses parent::create
  3. Attach to an Eloquent Model
  4. Try creating the model

Most helpful comment

Copying from the upgrade guide https://laravel.com/docs/5.4/upgrade

The create & forceCreate Methods

The Model::create & Model:: forceCreate methods have been moved to the IlluminateDatabaseEloquentBuilder class in order to provide better support for creating models on multiple connections. However, if you are extending these methods in your own models, you will need to modify your implementation to call the create method on the builder. For example:

public static function create(array $attributes = [])
{
    $model = static::query()->create($attributes);

    // ...

    return $model;
}

All 5 comments

The only option I can see is to modify my query to do (new static)->newQuery()->create($attributes);

This seems a little counter intuitive.

Copying from the upgrade guide https://laravel.com/docs/5.4/upgrade

The create & forceCreate Methods

The Model::create & Model:: forceCreate methods have been moved to the IlluminateDatabaseEloquentBuilder class in order to provide better support for creating models on multiple connections. However, if you are extending these methods in your own models, you will need to modify your implementation to call the create method on the builder. For example:

public static function create(array $attributes = [])
{
    $model = static::query()->create($attributes);

    // ...

    return $model;
}

@themsaid I can't believe I didn't see that. Thanks!

welcome :) It was only added a few days ago.

Wow did I need this today! Thanks!

Was this page helpful?
0 / 5 - 0 ratings