How to validate this context? In the validate method()? - laravel

Context: When a user creates a new conference he needs to select a start and an end date for the conference and the user needs to enter an end date after the start date, that is, the end date needs to be after the start date.
To deal with this logic properly, do you know if we can use the laravel validate method in the store method or is not a good approach or not possible do with this method? If it is not adequate to do this in the validate method do you know how to properly do that?
ConferenceController store method:
public function store(Request $request)
{
$this->validate($request, [
'conference_name' => 'required|max:255|string',
'conference_startDate' => 'required|date_format:d/m/Y',
'conference_endDate' => 'required|date_format:d/m/Y',
]);
$conference = Conference::create([
'nome' => $request->conference_name,
'startDate' => Carbon::parse($request->conference_startDate),
'endDate' => Carbon::parse($request->conference_endDate),
]);
}
Html fields:
<div class="form-row">
<div class="form-group col-md-6">
<label for="conference_startDate">Stard Date</label>
<div class="input-group date" data-provide="datepicker">
<input type='text' onkeydown="event.preventDefault()"
name="conference_startDate" value="{{ old('conference_startDate') }}"
class="form-control" placeholder="DD/MM/YYY" />
<span class="input-group-addon"><i class="fa fa-calendar text-primary" aria-hidden="true"></i></span>
</div>
</div>
<div class="form-group col-md-6">
<label for="conference_endDate">End Date</label>
<div class="input-group date" data-provide="datepicker">
<input type='text' class="form-control"
value="{{ old('conference_endDate') }}" name="conference_endDate" placeholder="DD/MM/YYY"/>
<span class="input-group-addon"><i class="fa fa-calendar text-primary" aria-hidden="true"></i></span>
</div>
</div>
</div>

As stated in the documentation, you could use the after rule:
after:date
The field under validation must be a value after a given date. The
dates will be passed into the strtotime PHP function:
'start_date' => 'required|date|after:tomorrow'
Instead of passing a
date string to be evaluated by strtotime, you may specify another
field to compare against the date:
'finish_date' => 'required|date|after:start_date'
So in your code:
$this->validate($request, [
'conference_name' => 'required|max:255|string',
'conference_startDate' => 'required|date_format:d/m/Y',
'conference_endDate' => 'required|date_format:d/m/Y|after:conference_startDate',
]);
Also, check this similar question.
Update
To check for a date after of equal another date, as stated in the docs, you should use:
after_or_equal:date
The field under validation must be a value after
or equal to the given date. For more information, see the after rule.

Related

Check dynamic variable of an array contains value or not in php

This is my basic form to create contacts in create.vue --
<div class="form-group mb-3 ">
<label class="form-label">Name</label>
<div>
<input type="text" class="form-control" placeholder="Enter Name" v-model="form.name" required>
</div>
</div>
<div class="form-group mb-3 ">
<label class="form-label">Contact Id</label>
<div>
<input type="text" class="form-control" placeholder="Enter Contact Id" v-
model="form.contact_id" required>
</div>
</div>
then I am giving the option to add address in the same form but which is not required. but if USER wants, while creating contact , user can add multiple addresses as well.
<div class="form-group row" v-for="(item, k) in form.addresses" :key="k" >
<label for="exampleFormControlInput1" class="form-label">Street 1:</label>
<div class="form-group mb-3">
<input class="form-control" type="text" v-model="item.street1" name="street1"
placeholder="Enter Street 1">
</div>
<div class="form-group mb-3">
<label for="exampleFormControlInput1" class="form-label">State</label>
<select class="form-control" v-model="item.state_id" name="state_id">
<option value="">Choose State</option>
<option value="1">Manitoba</option>
<option value="2">Winnipeg</option>
<option value="3">Punjab</option>
<option value="4">Other</option>
</select>
</div>
<div class="form-group mb-3">
<label for="exampleFormControlInput1" class="form-label">Country</label>
<select class="form-control" v-model="item.country_id" name="country_id">
<option value="">Choose Country</option>
<option value="1">Canada</option>
<option value="2">U.S</option>
<option value="3">India</option>
<option value="4">Other</option>
</select>
</div>
<div class="form-group mb-3">
<button class="btn btn-sm btn-danger" type="button"
#click="removeAddress(k)">Remove</button>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<input class="btn btn-primary form-control" type="button" value="Add Another Address"
#click="addAddress()">
</div>
</div>
But whenever i am storing the data in database, it should be stored if only name has been given .
In the controller, my data is being fetched like this if i use return $request->all()--
{"name":"y","contact_id":"y","addresses":"[{"street1":"y","state_id":"1","country_id":"1"}]"}
Below is my controller code --
public function store(Request $request)
{
//return $request->all();
$contact = Contacts::create([
'name' => $request->name,
'company_id' => Auth::user()->company_id,
]);
$addresses= json_decode($request->addresses, true);
//return $addresses;
//[{"street1":"","state_id":"","country_id":""}]
if (! empty($addresses)) {
foreach($addresses as $ad) {
$address = new Address;
$address->contact_id = $contact->id;
$address->street1 = $ad['street1'];
$address->state_id = $ad['state_id'];
$address->country_id = $ad['country_id'];
$address->save();
}
}
how to check if variable values of street, state and country is null, it should not store data.
It is returning me error
Invalid datetime format: 1366 Incorrect integer value: '' for column clientchief_db.addresses.state_id at row 1 (SQL: insert into addresses (contact_id, street1, state_id, country_id, updated_at, created_at) values (14, , , , 2022-06-14 19:26:49, 2022-06-14 19:26:49))"
You should validate your request:
$request->validate([
'addresses' => ['required', 'array'],
'addresses.*.street1' => ['required', 'string'],
'addresses.*.state_id' => ['required', 'numeric'],
'addresses.*.country_id' => ['required', 'numeric'],
]);
If I understand it right
User can fill up just name & submit the form - data should be persisted in the database
User can fill up multiple address, but if user doesn't fill up complete details (street, state & country should be filled) for the address it should not be persisted in the database
One approach would be to
validate the address data, ONLY if user added address to the form
and return validation error if street1, state_id or country_id is null
public function store(Request $request)
{
//return $request->all();
$validated = $request->validate([
'name' => ['required', 'string'],
'addresses' => ['sometimes', 'array'],
'addresses.*.street1' => ['sometimes', 'required', 'string'],
'addresses.*.state_id' => ['sometimes', 'required', 'numeric'],
'addresses.*.country_id' => ['sometimes', 'required', 'numeric'],
]);
//The above will pass validation if name is filled as non empty string & addresses is not present in the request data
//But if the addresses is present in the request, it will fail if either of street1, state_id or country_id is null
$contact = Contacts::create([
'name' => $request->name,
'company_id' => Auth::user()->company_id,
]);
$addresses= json_decode($request->addresses, true);
//return $addresses;
//[{"street1":"","state_id":"","country_id":""}]
if (! empty($addresses)) {
foreach($addresses as $ad) {
$address = new Address;
$address->contact_id = $contact->id;
$address->street1 = $ad['street1'];
$address->state_id = $ad['state_id'];
$address->country_id = $ad['country_id'];
$address->save();
}
}
//return response
}
Laravel Docs - Validation - Validating When Present

Input checkbox with multiple value on laravel

I'm making input using the checkbox, only hardware table need to input multiple checkbox values
When im trying using implode, i got appear errorException: "implode(): Invalid arguments passed".
Here my controller code :
auth()->user()->Form()->create
([
'user_id' => $request->user_id,
'os' => $request->os,
'hardware' => implode(',', $request->input('hardware')),
// $arrayToString = implode(',', $request->input('hardware'));
'software' => $request->software,
'signature' => $signature,
'status_desc' => $request->status_desc,
'cancel_deskripsi' => $request->cancel_deskripsi
]);
dd($form);
return redirect()->route('form')->with('status', 'success');
My view code:
<div class="form-group col-md-12">
<label>Hardware :</label>
<div class="checkbox-list">
<label class="form-group col-md-4">
<input type="checkbox" id="hardware" name="hardware[]" value="Komputer AIO">
<span></span>
Komputer AIO
</label>
<label class="form-group col-md-4">
<input type="checkbox" class="form-group" id="hardware" name="hardware" value="Laptop">
<span></span>
Laptop
</label>
<input id="other" name="how" type="checkbox" class="form-group">
<label for="other" class="form-group">Other :</label>
<div class="other-disclosure">
<input type="text" name="hardware" id="os-other" class="form-group col-md-2" placeholder="...">
</div>
</div>
How to solve this problem ?
You probably want to have all those inputs named hardware[] (so they will all end up in an array as the input hardware) and incase nothing is passed (unchecked checkboxes) you should make sure to handle this:
'hardware' => implode(',', (array) $request->input('hardware', []));
Here if nothing is passed then $request->input('hardware', []) is [], an array. The (array) cast is just to make sure there is an array being passed to implode.

Unique validation for mobile number field

I am inserting a mobile number in the database and I want to create unique validation as an email field. It can not run for my controller. Need changes
Controller:
$this->validate($req,
[
'client_name' =>'required',
'email'=>'required|unique:table_client_registration',
'mobileno'=>'numeric|unique:table_client_registration',
'password'=>'required',
'cpassword'=>'required|same:password'
],
$messages);
Blade:
<div class="row mt-3">
<div class="col">
<input type="text" name="mobile" class="form-control" placeholder="Enter Mobile No">
#if ($errors->has('mobileno')) <p style="color:red;">*{{ $errors->first('mobileno') }}</p> #endif
</div>
</div>
Your field name is mobile and you are trying to validate a mobileno..
So either change it in your view to this:
<input type="text" name="mobileno" class="form-control" placeholder="Enter Mobile No">
or in your validation
$this->validate($req,
[
'client_name' =>'required',
'email'=>'required|unique:table_client_registration',
'mobile'=>'numeric|unique:table_client_registration',
'password'=>'required',
'cpassword'=>'required|same:password'
],
$messages);

Laravel, adding data to database after verifying ReCaptcha

I'm using ReCaptcha in my Laravel project, done it with this
tutorial.
I need to create a page where user can post his message after checking captcha.
I have created a modal dialog where user can fill in data like this :
<form class="form-horizontal" action="" method="post">
<div class="form-group error">
<label for="messageName" class="col-sm-3 control-label">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control has-error" id="name" name="name" placeholder="Your name" value=""
ng-model="message.name" ng-required="true">
<span class="help-inline"
ng-show="GBM.text.$invalid && GBM.text.$touched">Required</span>
</div>
</div>
<div class="form-group error">
<label for="messageEmail" class="col-sm-3 control-label">Email</label>
<div class="col-sm-9">
<input type="email" class="form-control has-error" id="email" name="email" placeholder="E-mail" value=""
ng-model="message.email" ng-required="true">
<span class="help-inline"
ng-show="GBM.email.$invalid && GBM.email.$touched">Required</span>
</div>
</div>
<div class="form-group error">
<label for="messageLink" class="col-sm-3 control-label">Web</label>
<div class="col-sm-9">
<input class="form-control" rows="3" class="form-control has-error" id="web" name="web" placeholder="Link for your web" value="" ng-model="message.web" ng-required="false" >
</div>
</div>
<div class="form-group error">
<label for="messageText" class="col-sm-3 control-label">Comment</label>
<div class="col-sm-9">
<textarea class="form-control" rows="3" class="form-control has-error" id="comment" name="comment" placeholder="Your comment" value="" ng-model="message.text" ng-required="true" ></textarea>
<span class="help-inline"
ng-show="GBM.text.$invalid && GBM.text.$touched">Required</span>
</div>
</div>
{!! csrf_field() !!}
<!-- recaptcha -->
{{Request::is('contactd')}}
<div class="form-group">
<div class="col-md-9">
<div class="g-recaptcha" data-sitekey="{{env('GOOGLE_RECAPTCHA_KEY')}}"></div>
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-9 control-label"></label>
<div class="col-md-9">
<button type="submit" name="send" class="btn btn-primary btn-lg btn-block">Add new message <span class="fa fa-paper-plane-o"></span></button>
</div>
</div>
</form>
For a route I got it like this:Route::post('contact','ContactController#store');
And here is the problem, in my controller i got this code to verify captcha:
public function store(ReCaptchataTestFormRequest $request){
return "Captcha done right! ";}
And this code to save data to database
public function store(Request $request)
{
$this->validate($request, [ 'name' => 'required|max:255' ]);
$this->validate($request, [ 'email' => 'required | email' ]);
$this->validate($request, [ 'comment' => 'required' ]);
$ip = $_SERVER['REMOTE_ADDR'];
$browser = $_SERVER['HTTP_USER_AGENT'];
$guestbook = Guest_books::create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'web' => $request->input('web'),
'comment' => $request->input('comment'),
'ip' => $ip,
'browser' => $browser
]);
return $guestbook;
}
So the question is: What to write in Controller for project to verify Captcha and then post it to database?
The tutorial you've followed teaches you how to create a custom validation rule which you can then use when validating requests, either through a Form Request or directly in your controller.
The mistake you've made in your controller is that you've called validate multiple times, instead you should pass it an array containing all of your rules, including your recaptcha rule, e.g:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'email' => 'required|email',
'comment' => 'required',
'g-recaptcha-response' => 'required|recaptcha',
]);
// ...
}
Additionally, you should note that the store method should always return a redirect.

Laravel Custom Validation of Two Dates

I'm creating a form in Laravel which has two fields: departure-date and return-date. I'm trying to create custom validation logic where the departure date entered MUST be on the same day or any other date after the user fills in the form. The return-date should also be after the departure date. Kindly assist?
Form Layout
<!-- Departure date-->
<div class="form-line registar2 love {{ $errors->has('departure_date') ? ' has-error' : '' }}">
<input type="date" class="form-input" name="departure_date" value="{{ old('departure_date') }}" required>
<label>Departure Date *</label>
<div class="error-label">Field is required!</div>
<div class="check-label"></div>
#if ($errors->has('departure_date'))
<span class="help-block">
<strong>{{ $errors->first('departure_date') }}</strong>
</span>
#endif
</div>
<!--End departure-->
<!-- Return date-->
<div class="form-line registar2 move {{ $errors->has('return_date') ? ' has-error' : '' }}">
<input type="date" class="form-input" name="return_date" value="{{ old('return_date') }}" required>
<label>Return Date *</label>
<div class="error-label">Field is required!</div>
<div class="check-label"></div>
#if ($errors->has('return_date'))
<span class="help-block">
<strong>{{ $errors->first('return_date') }}</strong>
</span>
#endif
</div>
<!-- End return date-->
Validation in Controller
public function validatePlanEntries(Request $request)
{
$validation = $this->validate($request, [
'departure_date' => 'required',
'return_date' => 'required'
]
);
}
public function validatePlanEntries(Request $request)
{
$validation = $this->validate($request, [
'departure_date' => 'required|date|after:now',
'return_date' => 'required|date|after:departure_date',
]
);
}
FYI: the after:xxxxx rule either compares to another input field or respects the rules of the native DateTime PHP class. So you may enter after:now +2 hours.
To override the messages and write your own, create a messages() function like this:
public function messages()
{
return [
'departure_date.required' => 'Departure date is required',
'departure_date.after' => 'Please choose a date in the future',
'return_date.required' => 'Return date is required',
'return_date.after' => 'Your return date is before departure'
];
}
Just in case you are looking for a jquery solution to make datepicking more user friendly and less error bound, you may have a look at Bootstrap Datepicker, it's probably worth the effort. Good luck on your project!

Resources