Alex Lomia
Alex Lomia

Reputation: 7235

How to create a new record without executing a database query?

I have Question and Answer models. The Question hasMany Answers. Following commands run in the php artisan tinker mode invoke a database query for no apparent reason:

$q = new Question;
$q->answers[] = new Answer; // invokes the below query

// the executed query
select * from `answers` where `answers`.`question_id` is null and `answers`.`question_id` is not null

As you see, there is no need for database call whatsoever. How can I prevent it?

Upvotes: 1

Views: 176

Answers (2)

Joel Hinz
Joel Hinz

Reputation: 25404

When you do $q->answers, Laravel tries to load all of the answers on the question object - regardless of whether they exist or not.

Any time you access a relationship on a model instance, you can either call it like answers() and get a query builder back, or you can call it like answers without parentheses and Laravel will fetch a collection for you based on the relationship.

You can prevent it easily by doing this:

$q = new Question;
$a = new Answer;

And then, when you're ready to save them, associate them with each other. In its simplest form, that looks like this:

$q->save();
$q->answers()->save($answer);

Upvotes: 3

Josh
Josh

Reputation: 3288

It's doing that because you're assigning it to the Question object. It wants to see if you're adding an extant record reference. All Laravel Eloquent models contain magic methods for properties, and trying to use them as temporary data storage is a really bad idea unless you've defined a property on them ahead of time for that specific purpose.

Just use a regular array instead and then associate them after the models have been prepared.

Documentation on one-to-many relationships:
https://laravel.com/docs/5.1/eloquent-relationships#one-to-many

Upvotes: 1

Related Questions