Reputation: 2150
I'm trying to find a different approach on saving/updating a given model and it's relationships into database.
Basically I have a form for the "Author" page where multiple "Books" can be added. Naturally the "Author" and "Book" models have a one-to-many relationship.
According to the laravel official tutorial you have to:
Laravel also states that "Sometimes you may wish to save not only a model, but also all of its relationships. To do so, you may use the push method: $user->push();".
But I couldn't find any tutorial on how to fill the "Author" model with "Book" relationships and in fact use the push() method
I'm searching for something like this:
$author = new Author();
$author->name = "Bill Jobs";
$author->phone = "555 - 123456";
// fill model with relations
$author->addRelation($relationsArray)
if($author->push())
{
// ....
}
Also the same should work for updating an "Author": Firstly delete already stored relations, than save the new ones
Upvotes: 1
Views: 6038
Reputation: 93
you can update your book and author model using push method.
$book = Book::first();
$book->author->author_name = "Mark Twin";
$book->book_name = "Life On The Mississippi";
$book->push();
here is link for details [1]: https://medium.com/@JinoAntony/10-hidden-laravel-eloquent-features-you-may-not-know-efc8ccc58d9e
Upvotes: 0
Reputation: 81167
push
description below, as well as difference between createMany
and saveMany
relation mothodsEloqeunt doesn't handle deferred relationships (like for example Doctrine2), ie. you can't do this:
$author = new Author;
$book = new Book;
$book->author()->associate($author);
$author->push();
Because the association is done exactly, when you call associate
method. And all it does is this:
$child->foreign_key = $parent->primary_key;
So in the situation above, primary_key
is null
, because $author
has not been saved yet.
Next, while push
is not said to create the associations in the docs, it may make such impression and one might be tempted to do this:
$author = Author::first(); // existing parent
$books = Book::get(); // existing children collection
$author->books = $books;
$author->push();
However, this will not work as well. First off, Eloquent doesn't let you assign relation explicitly, like above, then, even if you do it properly, still the association will not be made:
$author = Author::first();
$books = Book::get();
$author->setRelation('books', $books);
$author->push();
This time, the relation was assigned properly, but still the association (assigning foreign keys) was not made. So despite both author
and all the books
will be saved/updated, they won't be associated at all.
push
OR leverage Eloquent methods (createMany
/ saveMany
):Start with:
$author = Author::find($someId);
// delete existing books
$author->books()->delete();
1 then manually:
// for example:
$booksInput = Input::get('books');
// validate etc
foreach ($booksInput as $bookArray)
{
$book = new Book;
// assign the value from, eg.
$book->fill($bookArray);
$book->author()->associate($author);
// or set FK explicitly
$book->author_id = $author->getKey();
// add to the author's collection
$author->books->add($book);
}
$author->push(); // saves author and each of the books in separate queries
2 or createMany
:
$booksAsArrays = Input::get('books'); // array of arrays
// validation
$author->books()->createMany($booksAsArrays); // associate and save each book
3 or saveMany
:
$booksAsModels = []; // array of Book models
$booksAsArrays = Input::get('books'); // array of arrays
// validation
foreach ($booksAsArrays as $bookArray)
{
$booksAsModels[] = new Book($bookArray);
}
$author->books()->saveMany($booksAsModels); // associate and save each book
Upvotes: 8
Reputation: 3588
For create many:
$author->books()->createMany($relationsArray);
Firstly delete already stored relations, than save the new ones
Then
$author->books()->delete(); // or if you are using soft delete forceDelete()
$author->books()->createMany($relationsArray);
Upvotes: 0