1

Given the following models:

Car Model
- parts: hasMany(Parts::class)

Part Model
- car: belongsTo(Car::class)

Running

Car::find(1)->parts()->saveMany(Part::hydrate($request->parts));

properly returns a list of Parts, 3 have id, one does not, so that's 3 models that need to be updated and one needs to be inserted. However looking at my database, not a single row is inserted and issuing dd(Car::find(1)->parts) returns an empty array. createMany works, but that does not update the models that have an id - instead it creates new ones. From the documentation,

If you need to save multiple related models, you may use the saveMany method

...

the difference between save and create is that save accepts a full Eloquent model instance while create accepts a plain PHP array

So what is the reason createMany works but saveMany does not?

Community
  • 1
  • 1
Iskren
  • 1,301
  • 10
  • 15

2 Answers2

0

You have explained it yourself, via your quote from the docs.

saveMany() uses eloquent models, this would be great for updating already existing parts. It does not work with generic arrays which I assume $request->parts is from your front-end.

createMany() uses generic arrays, since your $request->parts (Again I'm assuming) is an array it passes.

  • `$request->parts` is indeed an array, however `Part::hydrate($request->parts)` returns a collection of `Part` models from the input. Now, I can iterate over that collection and call `save()` on each object but with thousands of parts this is a very poor way of doing this. I just don't know why `createMany` works with an array and `saveMany` does not with a collection of models when the documentation states it is the intended way to use them. – Iskren Jun 18 '19 at 10:55
  • Could you try hydrating them before plugging it in to the saveMany function? `$hydrated = Part::hydrate($request->parts)` then plug in $hydrated? just to see if it's any different? –  Jun 18 '19 at 10:56
  • Just tried iterating over `$hydrated` and calling `->save()` on each instance - none seem to work. The issue is probably coming from somewhere else (possibly because I'm not running validation on the input yet...) – Iskren Jun 18 '19 at 11:03
0

This is a misuse of Post::hydrate. The hydrate function returns a collection of models that are marked as if they're coming from the database. Since after hydration nothing is changed, save() is being ignored because there are no changes made to them. Furthermore, saveMany() doesn't care for the id specified and it creates a new objects indiscriminately. In the end I moved validation to the related model and do a delete()/createMany() on each update.

Iskren
  • 1,301
  • 10
  • 15