gaiustemple's avatar

Eloquent new vs make

Hi,

Am I right in thinking that

$xyz = SomeModel::make([
	'attributes' => $abc
]);
$xys->save();

Is just an arguably nicer way of doing

$xyz = new SomeModel([
	'attributes' => $abc
]);
$xyz->save();

Is make going to be deprecated (or is it in the docs and I just missed it)?

0 likes
7 replies
chaudigv's avatar

make creates a model instance BUT does not persist it to the database i.e. model is not saved untill you call the save method.

Is make going to be deprecated

I don't think so because make method is usually used during unit tests, at least that's how I use it. Where I just want to make a user and run some validation tests on it before saving it to db.

gaiustemple's avatar

Thanks for the reply!

Yes ok, that's what I thought. I think new SomeModel() does the same, it doesn't insert it until ->save() is called.

https://laravel.com/docs/8.x/eloquent#inserts

They must just do the same thing? Just make doesn't seem to be documented (I came across it in livewire/surge).

tykus's avatar

Unfortunately it is not possible to document every single aspect of the framework, but the API documentation is a useful tool to know and browse.

https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Builder.html#method_make

You can follow the paths of make and __construct to see how they are broadly similar. The make method is particularly useful if you wished to fluently chain further methods on the Model instance, whereas new typically requires assignment to a temporary variable (not strictly necessary either, but that depends on your code styling preference).

pilat's avatar

Just wanted to mention this:

Larastan shouts on me:

 Called 'Model::make()' which performs unnecessary work, use 'new Model()'.
         🪪  larastan.noModelMake

So, I consider that someone has investigated this topic and came to conclusion that it makes sense to use new Model() syntax.

kevinbui's avatar

@gaiustemple @pilat nope, I don't think so. I believe the make method is a more advanced way to create a new model instance and should be the recommended way.

Looking at the source code:

// Illuminate\Database\Eloquent\Builder
public $pendingAttributes = [];

public function make(array $attributes = [])
{
    return $this->newModelInstance($attributes);
}


public function newModelInstance($attributes = [])
{
    $attributes = array_merge($this->pendingAttributes, $attributes);

    return $this->model->newInstance($attributes)->setConnection(
        $this->query->getConnection()->getName()
    );
}

The make method make use of that $pendingAttributes property, so we can configure predefined attributes for a new model instance. The make method is a more superior way to generate models.

I also don't agree with that Larastan's statement.

JussiMannisto's avatar

The make method make use of that $pendingAttributes property, so we can configure predefined attributes for a new model instance. The make method is a more superior way to generate models.

That's not what the property is for. It's used by the Eloquent builder. If you want default values, you use the $attributes property. And if you want custom values, you pass them in the constructor like they did.

Calling make() is unnecessary if you just want a model instance. So I agree with Larastan.

1 like
kevinbui's avatar

You are probably right, we aren't able to predefine default attributes for new model instances using that $pendingAttributes property.

But I have just found out that we can do the followings with that attribute:

use App\Models\Movie;

Movie::query()
	->withAttributes([
        'title' => 'The Godfather',
        'imdb_id' => 'tt0068646',
        'release_year' => 1972,
    ])
    ->make();

These two approaches probably do the same thing, I personally still prefer to use the make method.

Please or to participate in this conversation.