Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent saving an object with children

I am trying to save an order with order_items but I am not really finding anything in the docs to support this use case. A hasMany relationship.

Basically there is an orders table with something like id | user_id and an order_items table with id | order_id | product_id.

How can I save() the order and use an array of items at the same time without having to loop over the items and save them individually?

Is this possible?

Pseudo code assuming $items is an array:

$items = Session::get("cart.items");

$order = new Order;
$order->user_id = Auth::user()->id;
$order->order_items = $items;
$order->save();
like image 520
Jazzy Avatar asked Jul 17 '14 05:07

Jazzy


2 Answers

What you need for a hasMany relation is either saveMany or createMany, depending on what's in your $items array:

// array of attributes:
$items = [
  ['name'=>'item1','price'=>'price1'],
  ...
];

// then createMany:
$order->orderItems()->createMany($items);

This will create new rows in Items table.


// array of models:
$items = [
  Item::find($someId),
  Item::find($anotherId),
  // and/or newly instantiated:
  new Item(['name'=>'item1','price'=>'price1']),
  ...
];

// then createMany:
$order->orderItems()->saveMany($items);

This will associate (save) existing models, and create non-existing ones.


Also notice that I use camelCase relation name orderItems instead of your order_items. This is an important detail, since Eloquent (Laravel v4) looks for camelCased methods on the model when working with relations (dynamic properties).

//Order model
public function orderItems()
{
  return $this->hasMany(...);
}

$order->orderItems; // collection
$order->order_items; // collection as well

// --------------------
// BUT
public function order_items()
{
  return $this->hasMany(...);
}

$order->orderItems; // null
$order->order_items; // null

// the only way you can work with relation then, is explicitly use method like:
$order->order_items()->get(); 
like image 75
Jarek Tkaczyk Avatar answered Oct 08 '22 16:10

Jarek Tkaczyk


Probably not the best solution you are looking for, but this should work.

Let's say that the array is named $items, I'm under the impression that you will be saving it into a pivot table. In my example below I also have a 3rd field on item_order pivot table named item_quantity.

foreach ($items as $item)
{
    $order->items()
    ->attach($item['item_id'], ['item_quantity' => $item['item_quantity']]);
}

Basically you will be looping through the $items array. This will assume that you have defined the relationship on your Order model called items().

Then use the attach() method

->attach([insert the item_id], array('3rd field name' => 'value to be inserted')

Finally, if you don't have a 3rd field on your pivot table you could just do

->attach($item_id)

You can check the example given at the Laravel docs

Note

attach() is the method used when the you are only creating a record on the Database, otherwise you need a different method when you want to update.

like image 27
lozadaOmr Avatar answered Oct 08 '22 17:10

lozadaOmr