Reputation: 7128
I would like to know how do you update JSON column data while there is other columns need to be updated as well.
As I saw samples in laravel website it's something like this for json column
DB::table('users')
->where('id', 1)
->update(['options->enabled' => true]);
but what about other columns?
here is what I have currently:
public function update(Request $request, $id)
{
$order = Order::find($id);
$this->validate($request, array(
'payment_id'=>'nullable',
'orderstatus_id' => 'required|numeric',
'address_id' => 'required|numeric',
));
$order = Order::where('id',$id)->first();
$order->payment_id = $request->input('payment_id');
$order->orderstatus_id = $request->input('orderstatus_id');
$order->address_id = $request->input('address_id');
$order->save();
return redirect()->route('orders.index',
$order->id)->with('success',
'Order updated successfully.');
}
and I have column named product_name
which is Json type column and in it I have data such sample below, where I want to edit quantity
of products inside that for example.
{"29": {"id": 29, "name": "effewf", "price": 24524, "quantity": 3, "attributes": [], "conditions": []}, "37": {"id": 37, "name": "test product", "price": 456346, "quantity": 2, "attributes": [], "conditions": []}}
As you can see in this order I have 2 products, one with quantity of 3
and another with quantity of 2
.
Upvotes: 1
Views: 4264
Reputation: 3299
The Laravel documentation has a section on arrays and JSON. The way to do this would be to add the $casts
property to your Order
model:
protected $casts = [
'product_name' => 'array',
];
In your blade views and controllers, you should be able to then access $order->product_name
directly - no more need for doing any json_decode()
calls.
When updating specific values, in your 'edit order' view, you'll probably want to have your form inputs named something similar to make it easy to map your updates, i.e. something similar to:
@foreach($order->product_name as $data)
<label>Name:</label>
<input
type="text"
name="product_name[{{ $data['id'] }}][name]"
value="{{ $data['name'] }}"
>
<label>Price:</label>
<input
type="text"
name="product_name[{{ $data['id'] }}][price]"
value="{{ $data['price'] }}"
>
<label>Quantity:</label>
<input
type="number"
name="product_name[{{ $data['id'] }}][quantity]"
value="{{ $data['quantity'] }}"
>
@endforeach
This means that in your controller's update()
method, you can use the new values fetched from the request input like normal. If you want to strictly follow the format from the documentation, you should also set it in a new variable rather than setting it directly, i.e.
public function update(Request $request, $id)
{
$order = Order::find($id);
// ... other usual stuff
// get original data
$new_product_name = $order->product_name;
// contains all the inputs from the form as an array
$input_product_name = $request->input('product_name');
// loop over the product array
foreach ($input_product_name as $data_id => $data) {
// loop over each input for the product in the view form
foreach ($data as $key => $value) {
// set the new value
$new_product_name[$data_id][$key] = $value;
}
}
// set the new data (should automatically serialize into JSON for storage)
$order->product_name = $new_product_name;
$order->save();
}
Upvotes: 3
Reputation: 163788
The best way to handle this is to create a model and a table for this data.
But if you want to use JSON, you can use the casts
property in the model:
protected $casts = [
'product_name' => 'array',
];
Then, you'll be able to work with options as with an array:
$order = Order::where('id',$id)->first();
$order->payment_id = $request->input('payment_id');
$order->orderstatus_id = $request->input('orderstatus_id');
$order->address_id = $request->input('address_id');
$order->product_name[$request->product_id]['quantity'] = $request->new_product_quantity);
$order->save();
If you don't want to use casts, you can convert data manually:
$order->product_name = json_encode(
json_decode($order->product_name, true)[$request->some_product_id]['quantity'] = $request->new_quantity
);
Upvotes: 1