Reputation: 7128
I have drop-down where i show my products attributes, and no matter if i select any option or not it will add all the options to my cart under selected product.
what i need is to just get selected options or leave it empty if nothing has selected.
here is my blade code:
<tbody>
@foreach($options as $optiontitle => $optioncollection)
<tr>
<td style="width: 150px;">{{ $optiontitle }}</td>
<td class="text-left">
<select name="attr" class="form-control">
<option value="">Select</option>
@foreach($optioncollection as $suboption)
<option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
@endforeach
</select>
</td>
</tr>
@endforeach
</tbody>
here is my controller method for attributes
which i call them option
$options = $product->suboptions->mapToGroups(function ($item, $key) {
return [$item->option->title => $item];
});
and this is my cart method where thing happen and everything will be add to cart instead of selected only.
public function addingItem(Request $request, $id)
{
$product = Product::where('id', $id)->firstOrFail();
$customAttributes = [];
if(!empty($product->suboptions)){
foreach($product->suboptions as $subs) {
array_push($customAttributes, [
'attr' => [
'label' => $subs->title,
'price' => $subs->price,
]
]);
}
}
Cart::add(array(
'id' => $product->id,
'name' => $product->title,
'price' => $product->price,
'quantity' => $request->input('quantity'),
'attributes' => $customAttributes,
));
Session::flash('success', 'This product added to your cart successfully.');
return redirect()->back();
}
What I need to get is options title
and price
(take a look at my order sample to see why and where I need those)
"[{\"id\":29,\"name\":\"effewf\",\"price\":24524,\"quantity\":1,\"attributes\":[{\"attr\":{\"label\":\"Gray\",\"price\":\"7000.00\"}},{\"attr\":{\"label\":\"Red\",\"price\":\"5000.00\"}},{\"attr\":{\"label\":\"15\\\"\",\"price\":\"500000.00\"}},{\"attr\":{\"label\":\"17\\\"\",\"price\":\"700000.00\"}},{\"attr\":{\"label\":\"22\\\"\",\"price\":\"900000.00\"}}],\"conditions\":[]}]"
As you see in my attributes
part I have nested array such as :
\"attributes\":[{\"attr\":{\"label\":\"Gray\",\"price\":\"7000.00\"}},....
here is where I get that label
and price
in my function loop.
If I use loop such as:
foreach($request->attr as $subs) {
array_push($customAttributes, [
'attr' => [
'label' => $subs->title,
'price' => $subs->price,
]
]);
Instead of what I have I will get this error:
Trying to get property of non-object
on this line:
'attr' => [
'label' => $subs->title,
'price' => $subs->price,
PS:
If I use $customAttributes = $request->attr;
with my own loop (at the top) I will get id
of selected option only, which is no good to me.
Upvotes: 2
Views: 2647
Reputation: 1108
Shouldn't you get the options from an order or The Request and not from the Prodect ?!
Because the product should obviously have all options.
...........
-Edit:1
Change your loop like this
foreach($request->attr as $subs)
and change your selct tag to look something like this
<select multiple>
-Edit2
After editing your question, I think you have two options:
OR
Serialize the title and price in the front end html option tag so that you will end up with something like this:
<option value="{{$suboption->title.','.$suboption->price}}" .....> .....</option>
then inside your loop do like this:
foreach($request->attr as $subs) {
$title_and_price = explode(',', $subs);
array_push($customAttributes, [
'attr' => [
'label' => $title_and_price[0],
'price' => $title_and_price[1]
]
]);
-Edit:3
We should also add square brackets to the name in the select tag like this:
<select name="{{ $optiontitle }}[]" multiple>
Edit:4 I found another problem:
you should use name = "{{ $optiontitle }}[]" in the select because they canot all have the same name thus, you have to make the name attribute of the select tag dynamic as well
Upvotes: 1
Reputation: 1704
Try replacing Controller Function addingItem with below
public function addingItem(Request $request, $id)
{
$product = Product::where('id', $id)->firstOrFail();
$customAttributes = [];
if(!empty($product->suboptions)){
foreach($product->suboptions as $subs) {
array_push($customAttributes, [
'attr' => [
'label' => $subs->title,
'price' => $subs->price,
]
]);
}
}
Cart::add(array(
'id' => $product->id,
'name' => $product->title,
'price' => $product->price,
'quantity' => $request->input('quantity'),
'attributes' => $request->input('attr'), // Attributes Array
));
Session::flash('success', 'This product added to your cart successfully.');
return redirect()->back();
}
I assume you need to insert multiple attributes by
@foreach($options as $optiontitle => $optioncollection)
replace the blade code,
<tbody>
@foreach($options as $optiontitle => $optioncollection)
<tr>
<td style="width: 150px;">{{ $optiontitle }}</td>
<td class="text-left">
<select name="attr" class="form-control">
<option value="">Select</option>
@foreach($optioncollection as $suboption)
<option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
@endforeach
</select>
</td>
</tr>
@endforeach
</tbody>
with below
<tbody>
@foreach($options as $optiontitle => $optioncollection)
<tr>
<td style="width: 150px;">{{ $optiontitle }}</td>
<td class="text-left">
<select name="attr[]" class="form-control">
<option value="">Select</option>
@foreach($optioncollection as $suboption)
<option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
@endforeach
</select>
</td>
</tr>
@endforeach
</tbody>
it will create an attribute array which will prevent the error,
Trying to get property of non-object
If you need further assistance, leave a comment.
Upvotes: 0
Reputation: 6625
Because you called your product's suboptions
relationship instead of getting it from the request.
You are calling it with this $product->suboptions
instead of getting it from the request.
$customAttributes = $request->attr; // try to dd($customAttributes) so you can see it
UPDATE:
You only need to pass the id to your options
<select name="attr[]" class="form-control" multiple>
<option value="">Select</option>
@foreach($optioncollection as $suboption)
<option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
@endforeach
</select>
and in your Controller, fetch them and validate
public function addingItem(Request $request, $id)
{
$product = Product::findOrFail($id);
$customAttributes = [];
if (!empty($request->attr)) {
foreach ($request->attr as $sub) {
// You should fetch the price from the database NOT from the user
// request as it will be very vulnerable to attacks
// find the suboption
$sub = Suboption::find($sub); // Here I assume you have the Model
// for your Product's suboptions
if (!empty($sub->id)) {
array_push($customAttributes, [
'attr' => [
'label' => $sub->title,
'price' => $sub->price,
]
]);
}
}
}
Cart::add(array(
'id' => $product->id,
'name' => $product->title,
'price' => $product->price,
'quantity' => $request->input('quantity'),
'attributes' => $customAttributes,
));
Session::flash('success', 'This product added to your cart successfully.');
return redirect()->back();
}
Upvotes: 4