Eloquent Create, Update, New…the Untold Story

Like zombies, they lurch forward out of the swirling fog of the documentation, threatening your peace of mind…`firstOrNew`. `firstOrCreate`. `updateOrCreate`. You can look away, but you can never forget they’re there…

Okay, probably better saved for Halloween than April Fool’s. Still, for a great many of us, it captures the feeling, doesn’t it? We know they must be for something, and the fact that we don’t know for what leaves us slightly unsettled. Over on Laravel Quick Tips we’ve been looking at a few of these functions and their uses, and I thought it might be helpful to collect all of them together in a single (I hope) coherent post.

Without further preamble, let’s get to it. I’m going to use the basic User object and table that ships with a default installation of Laravel so you can follow along if you like.

New vs. Create

Let’s start by answering one of the fundamental differences in creating new records — what is the difference between using these two bits of code?

User::create(['name' => 'Jeff']); $user = new User(['name' => 'Joe']); $user->save();

The answer is a simple one — `create` actually creates and saves the record; the second method creates a new User instance but does not fire the save() method. Don’t believe me? Have a look at Illuminate\Database\Eloquent\Model::create. It looks exactly like the second example!

Why would we do that? Why take the extra steps if we have a nice wrapper function? Because we are using an ORM. Something I see that is very common, and I think a mistake, is to ignore the fact that you are using an ORM and instead set up your relationships manually.

For example:

new Post::create(['user_id' => 1, 'title' => 'The title']);

This is bad for a couple of reasons. First — isn’t that the job of the ORM? Of course it is! Compare:

$post = Post::create(['title' => 'The title']); User::find(1)->posts()->save($post);

Not only do I let my ORM do the work, but it gives me added security of checking that I’ve got the right User and they exist. (Better still is to write this with findOrFail, for example).

BUT!! I have a problem, which ties us back in to my original point. If you have set up your foreign keys correctly, this second method will fail! Why? Because you are tying to `create` the Post without the user_id, which will be required. That’s why we simply make a new instance without saving it.

$post = new Post(['title' => 'The title']); User::find(1)->posts()->save($post);

In this case, Laravel will add the `user_id` itself, based on your relationship info. There are a few ways of making a new instance without saving (using factories, for example, which we’ll touch on when we look into testing more), but this is the most straightforward.

findOrNew, firstOrCreate, updateOrCreate, …


Originally published at www.laravelfeed.com.