Bulk insertion of array of eloquent models - laravel

Is it possible to insert several eloquent models in one query?
Let's say I have eloquent model Page and I want to insert array of pages or collection of pages in one query
$page1 = new Page();
$page2 = new Page();
$pages = [
$page1,
$page2,
];
or
$pages = Collection([$page1, $page2]);
I want something like
$pages->save();
But it warns that "Method save does not exist".
I saw this, but there they insert array of arrays and I want to insert array of eloquent models.

You could try the saveMany() option.
This example might work for you:
DB::table('pages')->saveMany($pages);
And if you are working with relationships you can even use a "cleaner" way (just showing you example of ways to use this function):
$book = App\Book::find(1);
$book->pages()->saveMany([
new App\Page(['title' => 'A new page.']),
new App\Page(['title' => 'Another page.']),
]);

Related

Loading relation of new model in Laravel

I just want to get hasOne relation of New model.
Can I load it before I will save it.
I have $user = new User(['order_id' => $order_id]);
How can I get $user->order; without build new request?
As others have already pointed out the model must be saved before retrieving any relations.
My usual approach for this is using lazy eager loading:
// Create new model with data
$newModel = Model::create([
'column' => $value
]);
// Use load to retrieve any relations
return $newModel->load('myRelationship');

Laravel create multiple records in one query with Eloquent and get the created models

I know I can do the following to create multiple records with one query :
$users = [];
$users[] = ['name' => 'Tom'];
$users[] = ['name' => 'Jerry'];
$result = User::insert($users);
The problem of this approach is that ìnsert uses the query builder, and returns a boolean.
What if I wanted to have the created Eloquent models returned ? Would that be possible without having to do another query to retrieve them (how would I do that since I don't know the created ids ?) ?
I'm looking for something like the create method (which returns the created User model), but for multiple inserts (afaik createMany does not work outside of relationships)
Thanks

Grab relation of saved Eloquent model

After I save a Eloquent model, how am I able to retrieve a relationship with it?
So for example:
$model = new Foo;
$model->save();
dd($model); //return an object of Foo
Let's say I've set an relation to Baz, I should grab the relation like a normal Eloquent Object.
dd($model->with('baz')->get());
But this is returning every Foo record in de database with the relationship.
I just want to be able to get the current Baz model which is related to the saved Foo model.
I could do:
$result = Foo::with('baz')->find($model->id);
dd($result);
But this results in another query, which I want to prevent.
Simply just access it once like this:
$model->baz
And the relationship will be loaded.
Alternatively you can lazy eager load the relation:
$model->load('baz');
The effect is the same, although the first way allows you to actually use the result of the relation directly. If you just want to have the relationship in your array / JSON output I suggest you use the second method, because it's clearer what you're doing.
Depends on how you declare your relationships on your models. Assuming your relationship is declared as One to Many like this:
class Foo extends Eloquent {
public function bazes()
{
return $this->hasMany('Baz');
}
}
Then you can try this:
$results = $model->bazes;
or
$results = Foo::find($id)->bazes
$results is an iterable collection of bazes related directly with foo->id = x
But if you want eager loading with filters, then you can try like this:
$result = Foo::with(array('bazes' => function($query)
{
$query->where('id', $id);
}))->get();
I hope this works for you.
You should eager load on existing models using load().
Try
$model = new Foo;
$model->save();
$model->load('baz');

Laravel Create Collection of a certain Model and add Objects manually

I got a list of IDs and need to get a Collection (Let's say of the type "Book") and add Single Books to this Collection by Hand.
Example:
$ids = array(1,5,7,12);
$books = ???
foreach($ids as $id){
$books->add(Book::find($id)); }
Or is there a easier way to get what I want?
Thank you
You could write something like this I think:
$books = Book::whereIn('id', $ids)->get();
$books will be a Collection containing all your books.

Laravel 4 - Get Array of Attributes from Collection

I have a collection of objects. Let's say the objects are tags:
$tags = Tag::all();
I want to retrieve a certain attribute for each tag, say its name. Of course I can do
foreach ($tags as $tag) {
$tag_names[] = $tag->name;
}
But is there a more laravelish solution to this problem?
Something like $tags->name?
Collections have a lists method similar to the method for tables described by #Gadoma. It returns an array containing the value of a given attribute for each item in the collection.
To retrieve the desired array of names from my collection of tags I can simply use:
$tags->lists('name');
Update: As of laravel 5.2 lists is replaced by pluck.
$tags->pluck('name');
More specifically, the laravel 5.2 upgrade guide states that "[t]he lists method on the Collection, query builder and Eloquent query builder objects has been renamed to pluck. The method signature remains the same."
Yep, you can do it nice and easily. As the Laravel 4 Documentation states, you can do
Retrieving All Rows From A Table
$users = DB::table('users')->get();
foreach ($users as $user)
{
var_dump($user->name);
}
Retrieving A Single Row From A Table
$user = DB::table('users')->where('name', 'John')->first();
var_dump($user->name);
Retrieving A Single Column From A Row
$name = DB::table('users')->where('name', 'John')->pluck('name');
Retrieving A List Of Column Values
$roles = DB::table('roles')->lists('title');
This method will return an array of role titles.
You may also specify a custom key column for the returned array:
$roles = DB::table('roles')->lists('title', 'name');
Specifying A Select Clause
$users = DB::table('users')->select('name', 'email')->get();
$users = DB::table('users')->distinct()->get();
$users = DB::table('users')->select('name as user_name')->get();
EDIT:
The above examples show how to access data with the help of Laravel's fluent query builder. If you are using models you can access the data with Laravel's Eloquent ORM
Because Eloquent is internaly using the query builder, you can without any problem do the following things:
$tag_names = $tags->lists('tag_name_label', 'tag_name_column')->get();
which could be also done with:
$tag_names = DB::table('tags')->lists('tag_name_label', 'tag_name_column')->get();
Here are a few snippets from my own experimentation on the matter this morning. I only wish (and maybe someone else knows the solution) that the Collection had a $collection->distinct() method, so I could easily generate a list of column values based on an already filtered collection.
Thoughts?
I hope these snippets help clarify some alternative options for generating a list of unique values from a Table, Collection, and Eloquent Model.
Using a Collection (Happy)
/**
* Method A
* Store Collection to reduce queries when building multiple lists
*/
$people = Person::get();
$cities = array_unique( $people->lists('city') );
$states = array_unique( $people->lists('state') );
// etc...
Using an Eloquent Model (Happier)
/**
* Method B
* Utilize the Eloquent model's methods
* One query per list
*/
// This will return an array of unique cities present in the list
$cities = Person::distinct()->lists('city');
$states = Person::distinct()->lists('state');
Using an Eloquent Model PLUS Caching (Happiest)
/**
* Method C
* Utilize the Eloquent model's methods PLUS the built in Caching
* Queries only run once expiry is reached
*/
$expiry = 60; // One Hour
$cities = Person::remember($expiry)->distinct()->lists('city');
$states = Person::remember($expiry)->distinct()->lists('state');
I would love to hear some alternatives to this if you guys have one!
#ErikOnTheWeb
You could use array_column for this (it's a PHP 5.5 function but Laravel has a helper function that replicates the behavior, for the most part).
Something like this should suffice.
$tag_names = array_column($tags->toArray(), 'name');

Resources