Laravel dropdown gets all options even if not selected - php

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();
}
UPDATE
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.

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();
}

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:
use the id from each $subs to query your suboptions again from the DB
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

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.

Related

how to create a coupon in laravel

Am currently working with coupon in the backend when i create the coupon and give an expiry date to it and change the date in my database it still shows valid.
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'discount' => 'required',
'validity' => 'required',
]);
Coupon::insert([
'name' => strtoupper($request->name),
'discount' => $request->discount,
'validity' => $request->validity,
'created_at'=> Carbon::now(),
]);
return redirect()->route('coupons');
}
<tbody>
#foreach($coupons as $coupon)
<tr>
<th scope="row">{{$coupon->id}}</th>
<td>{{$coupon->name}}</td>
<td>{{$coupon->discount}}</td>
<td>{{Carbon\Carbon::parse($coupon->validity)->format('D, d F Y')}}</td>
<td>
#if($coupon->validity >= Carbon\Carbon::now()->format('Y-m-d'))
<span class="badge text-bg-primary">Valid</span>
#else
<span class="badge text-bg-danger">Invalid</span>
#endif
</td>
<td>
Edit
Delete
</td>
</tr>
#endforeach
</tbody>
try with this
#if(Carbon\Carbon::parse($coupon->validity)->gt(Carbon\Carbon::now())
I recommend putting this logic inside a getter in your Coupon model. Make sure you cast your validity field to DateTime.
In your model, it should look like this
class Coupon extends Model {
protected $casts = [
'validity' => 'datetime',
];
public function getIsValidAttribute()
{
return $this->validity->gt(now());
}
}
And on your blade view you can use it like this
#if($coupon->is_valid)
Good luck

Nova Icon Select

I would like to integrate a list of icons in a drop-down list of a back office (laravel nova), I found something to help me on this link https://novapackages.com/packages/bernhardh/nova-icon-select
I followed all the procedure, but I block at the level of the display of my icons, I currently have this code in my models:
public static function getIconsOptions(): array
{
NovaIconSelect::make("Icon")
->setIconProvider(IconProvider::make()->setOptions([
[
'label' => 'aaaa',
'value' => '<i class="fa-brands fa-apple-pay"></i>',
],
[
'label' => 'aaaa',
'value' => 'my-icons-2',
],
[
'label' => 'aaaa',
'value' => 'my-icons-3',
],
]));
$options = [];
foreach(self::ICON_NAMES as $key => $icon)
$options[$key] = trans('appearance.'.$icon);
return $options;
}
and this code in my blade
<select class="js-visual-field w-full form-control form-input form-input-bordered" data-field-name="icon_select_{{ $i }}">
<option value="">{{ trans('nova-visual-composer::templates.'.$templateName.'.no_icon') }}</option>
#foreach(\App\Models\Appearance::getIconsOptions() as $key => $txt)
<option value="{{ $key }}">{{ $txt }}</option>
#endforeach
</select>
To render HTML in blade, you need to use {!! $txt !!} instead of {{ $txt }}. Otherwise, the string will be auto escaped. So:
<select class="js-visual-field w-full form-control form-input form-input-bordered" data-field-name="icon_select_{{ $i }}">
<option value="">{{ trans('nova-visual-composer::templates.'.$templateName.'.no_icon') }}</option>
#foreach(\App\Models\Appearance::getIconsOptions() as $key => $txt)
<option value="{{ $key }}">{!! $txt !!}</option>
#endforeach
</select>

Select multiple categories from one input field in Laravel 8

I want to select multiple categories in one input field, I have a code, but it is not working:
PostController:
foreach($request->category_id as $key => $value) {
Project::create([
'name' => $request->name,
'body' => $request->body,
'category_id' => $request->category_id[$key],
]);
}
Form:
<select name="category_id[]" id="category_id" class="selectpicker" data-style="btn btn-success btn-round" data-live-search="true" data-size="5" multiple>
#foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
If you want to have one Post in multiple categories, you need to change your Database also.
You cant have only one category_id in posts table.
You have to adapt Many To Many relationship (One Post can be in multiple categories, one Category can have multiple Posts).
More here: Laravel Docs
Than you can save it simple with one line (based on your code):
$post->categories()->sync($request->category_id);
Use this code in PostController
foreach($request->category_id as $value) {
Project::create([
'name' => $request->name,
'body' => $request->body,
'category_id' => $value,
]);
}

Laravel backpack edit form displaying checklist items with selected values from database

In my crud controller, There is one field called "roles (Multiple checklist)", While before saving the roles, I am converting array into string like 1,2,3 using implode.
Ex: CrudController
setUp() method
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
In Store method,
public function store(StoreRequest $request)
{
$sel_roles = $request->input("roles");
$roles = !empty($sel_roles) ? implode(",",$sel_roles) : "";
$request->request->set("roles",$roles);
//dd($request);
return parent::storeCrud($request);
}
Edit Method looks like this,
public function edit($id) {
$this->crud->hasAccessOrFail('update');
// get the info for that entry
$this->data['entry']= $this->crud->getEntry($id);
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
$this->data['crud'] = $this->crud;
$this->data['fields'] = $this->crud->getUpdateFields($id);
$this->data['id'] = $id;
return view('crud::edit', $this->data);
}
If am trying to access, Edit page, I am getting below error,
ErrorException in line 15:
Call to a member function pluck() on string (View: /var/www/html/app/vendor/backpack/crud/src/resources/views/fields/checklist.blade.php)
checklist.blade.php page looks like below
<div #include('crud::inc.field_wrapper_attributes') >
<label>{!! $field['label'] !!}</label>
<?php $entity_model = $crud->getModel(); ?>
<div class="row">
#foreach ($field['model']::all() as $connected_entity_entry)
<div class="col-sm-4">
<div class="checkbox">
<label>
<input type="checkbox"
name="{{ $field['name'] }}[]"
value="{{ $connected_entity_entry->id }}"
#if( ( old( $field["name"] ) && in_array($connected_entity_entry->id, old( $field["name"])) ) || (isset($field['value']) && in_array($connected_entity_entry->id, $field['value']->pluck('id', 'id')->toArray())))
checked = "checked"
#endif > {!! $connected_entity_entry->{$field['attribute']} !!}
</label>
</div>
</div>
#endforeach
</div>
{{-- HINT --}}
#if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
#endif
</div>
How do I display the roles with selected values in the edit page.
Thanks
After hours of debug and verified,
Send the edit values in the collection format,
$options = [
'name' => 'role_id',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
"value" => collect([$edit_value_array])
];

Solve laravel validation for field with relation

I have some problem where the validation is failing for my blade template with dropdown select on related table. I tried to searched for an answer but cannot found it.
To temporarily comment out the the field 'business_unit_id' inside the array in validate function to avoid the error.
In controller update function:
$item = CostCenter::findOrFail($id);
$validatedData = $request->validate([
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'business_unit_id' => 'required|integer',
]);
$item->fill($validatedData);
$item->business_unit_id = $request->businessUnit;
$item->save();
$request->session()->flash('status', 'Cost centers record was updated!');
return redirect()->route('costCenters.show', ['cost_centers' => $item->id]);
In blade template:
<label for="businessUnit" class="col-sm-2 col-form-label">Business Unit</label>
<select name="businessUnit" class="form-control">
#foreach (App\Models\BusinessUnit::all() as $data)
<option value="{{ $data->id }}"
{{ old('business_unit_id', $cost_centers->business_unit_id ?? '1')
!= $data->id ?: 'selected' }}>
{{ $data->code }} - {{ $data->descr }}
</option>
#endforeach
</select>
The notification received is "The business unit id field is required." with my error helper.
$validatedData = $request->validate([
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'businessUnit' => 'required|integer',
]);
Use businessUnit instead of business_unit_id
as we have to use the name of select tag...
don't use the id of options tag..
you can try this code...and use use keyword to of the code like use Validator;
$rules = [
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'businessUnit' => 'required|integer|exists:business_unit,id',
];
$message = [
'code.required' => 'code is required.',
'descr.required' => 'description field is required.',
'businessUnit.required' => 'The business unit id field is required.',
];
$validator = Validator::make($request->all(), $rules,$message);
if ($validator->fails()) {
$arr = array("status"=>400,"msg"=>$validator->errors()-
>first(),"result"=>array());
}
else
{
your code write in this section
}
For any request data validation in controller You can try like this:
$rule=array(
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'business_unit_id' => 'required|integer',
);
$validator= Validator::make($request->all(),$rule);

Categories