how to create a coupon in laravel - php

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

Related

Laravel 8: Multiple Select Option Does Not Send Data

I have two tables at db, one of them is named users which simply contains user information of website and the other one is tags which contains some hashtags that users can choose from them.
(just like Stackoverflow that a user can select multiple tags such as php, javascript & etc)
So in order to make this relationship between these two, I added this to User model:
public function tags()
{
return $this->belongsToMany(Tag::class);
}
And also this one to Tag model:
public function users()
{
return $this->belongsToMany(User::class);
}
And here is the select option on blade, and users can select multiple tags from db:
<select class="form-control BSinaBold" name="skills[]" id="skills" multiple>
#foreach(\App\Models\Tag::all() as $tag)
<option value="{{ $tag->id }}" {{ in_array($tag->id , Auth::user()->tags->pluck('id')->toArray()) ? 'selected' : '' }}>{{ $tag->name }}</option>
#endforeach
</select>
Then at the Controller, I added this in order to update data at tags table:
public function update(Request $request, $profile)
{
$validate_data = Validator::make($request->all(),[
'job' => 'nullable',
'stackoverflow' => 'nullable',
'github' => 'nullable',
'instagram' => 'nullable',
'linkedin' => 'nullable',
'website' => 'nullable',
'location' => 'nullable',
'skills' => 'array',
]);
$user = User::findOrFail($profile);
$user->update([
'job' => request('job'),
'stackoverflow' => request('stackoverflow'),
'github' => request('github'),
'instagram' => request('instagram'),
'linkedin' => request('linkedin'),
'website' => request('website'),
'location' => request('location'),
]);
$user->tags()->sync(request('skills'));
$user->save();
return view('profile');
}
And it works fine and perfect but the only problem is this line, that does not sync data at tags table:
$user->tags()->sync(request('skills'));
So I tried debugging and I found out that request('skills') is EMPTY!
So the question is, why it does not send any data to the Controller?
I would really appreciate any idea or suggestion from you guys...
Thanks in advance.
I think you define your model relation wrong.
Tag model should be:
public function user()
{
return $this->belongsTo(User::class);
}
and the User Model relations:
public function tags()
{
return $this->hasMany(Tag::class);
}
If you aim to establish a one-to-many relation.

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

Laravel dropdown gets all options even if not selected

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.

Model binding in registration form for Laravel 5.4

I am trying to pull list of data from database and show it as a dropdown in a registration form. But I get error undefined variable universities.
Register Controller
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
$universities = University::lists('id', 'university');
$sch_depts = Department::lists('id', 'department');
return User::create([
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'university' => $data['university'],
'school_dept' => $data['school_dept'],
])
->with(compact('universities','sch_depts'));
}
register.blade.php
<div class="form-group{{ $errors->has('university') ? ' has-error' : '' }}">
<label for="university" class="col-md-4 control-label">University</label>
<div class="col-md-6">
{!! Form::select('university', $universities, null, array('id' => 'universitiy', 'class' => 'form-control')) !!}
#if ($errors->has('university'))
<span class="help-block">
<strong>{{ $errors->first('university') }}</strong>
</span>
#endif
</div>
</div>
I am getting an error universities undefined.
Let's assume you have a controller called RegisterController, the create method should only return view and it's corresponding data.
public function create()
{
$universities = University::lists('id', 'university');
$sch_depts = Department::lists('id', 'department');
return view('register', compact('universities', 'sch_depts'));
}
and you should also have a store method:
public function store(\Illuminate\Http\Request $request)
{
// your validation goes here
// or just use form request validation
// docs: https://laravel.com/docs/5.4/validation#form-request-validation
User::create([
'firstname' => $request->get('firstname'),
'lastname' => $request->get('lastname'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password')),
'university' => $request->get('university'),
'school_dept' => $request->get('school_dept'),
]);
// login user here or redirect to success page
}
and your routes/web.php file should contain the following routes:
Route::get('register', 'RegisterController#create');
Route::post('register', 'RegisterController#store');
This is really basics of Laravel, please read the docs.
P.S. Laravel comes with great Authentication system, which you can override to your needs.
This is what I did in Laravel 7, I'm also using the default authentication implementation from Laravel, so it might help
The solution is: in the RegisterController overwrite the method showRegistrationForm (which is declared in /vendor/laravel/ui/auth-backend/RegisterUsers) and add the data array.
So you will add something like this to your RegisterController
public function showRegistrationForm()
{
$universities = University::lists('id', 'university');
$sch_depts = Department::lists('id', 'department');
return view(
'auth.register',
[
'universities' => $universities,
'sch_depts' => $sch_depts
]
);
}}

Categories