Ignore validation rules if input value is empty ("") - php

I have a form to create a conference and I have some validation rules like below. For example the city is not required but should be a string. The issue is that when the user click in the "Store" button without fill the non required fields it appears the validation errors like:
The city must be a string.
Do you know how to solve that issue? If the value of the form field is "" ignore the rules?
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string',
'categories' => 'array|between:1,3',
'city' => 'string',
'zip_code' => 'string',
]);
...
}

you can use nullable if anyone field is non requied field.below you can see the code...
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string',
'categories' => 'nullable|array|between:1,3',
'city' => 'nullable|string',
'zip_code' => 'nullable|string',
]);
...
}

Related

How to fetch and store data from other table to user table. Laravel 8

Form
{!! Form::select('grade_level[]', $grade_level,[], array('class' => 'form-control','multiple')) !!}
Controller
Here is my create function that will return the a view and the list of roles and grade level for users
public function create()
{
$grade_level = GradeLevel::pluck('grade_level','id')->all();
$roles = Role::pluck('name','name')->all();
return view('users.create',compact('roles','grade_level'));
}
Here is the store function. and I have encounter a problem MySql Error: 1364 Field 'grade_level_id' doesn't have default value
public function store(Request $request)
{
$this->validate($request, [
'f_name' => 'required',
'm_name' => 'required',
'l_name' => 'required',
'sex' => 'required',
'id_number' => 'required',
'address' => 'required',
// 'email' => 'required|email|unique:users,email',
'username' => 'required|unique:users',
'password' => 'required|same:confirm-password',
'grade_level_id' => 'required',
'roles' => 'required'
]);
$input = $request->all();
$input['password'] = Hash::make($input['password']);
$user = User::create($input);
$user->grade_level_id = $request->grade_level;
$user->assignRole($request->input('roles'));
return redirect()->route('users.index')
->with('success','User created successfully');
}
I see you're using User::create() method to add new user, you'd need to add grade_level_id to the fillable property or your User model.
protected $fillable = [
'grade_level_id'
];
Find More about it here : https://laravel.com/docs/8.x/eloquent#mass-assignment
Either add 'grade_level_id' to the $fillable of your user model,
or
inside your migration, you can add the ->nullable(); extension to the grade_level_id field declaration

Laravel 5 Update Validation email needs to be unique

I'm trying to update a user, as an admin.
I'm changing the username, but it says email must be unique.
How do I fix this.
public function update($id, PutUser $request)
{
if (auth()->id() == $id) {
return redirect()->back()->withFlashDanger('Permission Denied, You can not edit own profile here.');
}
$user = User::find($id);
$user->update((array_merge($request->validated(), ['county' => request('county')])));
//Update model_has_roles model with assignees_roles
return redirect()->route('users.index')->withFlashSuccess(trans("alerts.users.updated"));
}
This is the request class
public function authorize()
{
return true;
}
public function rules()
{
$user_id = $this->input('id');
return [
'name' => 'required|string',
'username' => 'required',
'email' => 'required|email|unique:users,email'.$user_id,
'gender' => 'required',
'phone' => 'sometimes|numeric',
'address' => 'sometimes|string',
'country_id' => 'required',
];
}
}
I keep getting a failed email validation. 'Email has already been taken'. Any idea
You are missing a comma after the email label in your validation:
return [
'name' => 'required|string',
'username' => 'required',
'email' => 'required|email|unique:users,email,'.$user_id,
'gender' => 'required',
'phone' => 'sometimes|numeric',
'address' => 'sometimes|string',
'country_id' => 'required',
];
Since Laravel 5.3 (I believe), you can also use rule builders for more descriptive validation rules. Those are better to read and interpret for humans so it would result in a lower error rate:
use Illuminate\Validation\Rule;
return [
'email' => [
'required',
Rule::unique('users', 'email')->except($user_id),
]
];
https://medium.com/#tomgrohl/why-you-should-be-using-rule-objects-in-laravel-5-5-c2505e729b40

Laravel Validator returns MethodNotAllowedHttpException Error

I have two form pages which accept POST methods in my routing:
web.php
Route::post('select-room', ['as'=>'select-room','uses'=>'ClientBookingController#selectRoom']);
Route::post('book-room', ['as'=>'book-room','uses'=>'ClientBookingController#bookRoom']);
The functionality works as this. I submit data in page 'select-room' to 'book-room'
There is validation in methods 'selectRoom' and 'bookRoom'
public function selectRoom(Request $request){
$this->validate($request, [
'start_date' => 'required|date|after:yesterday',
'end_date' => 'required|date|after:start_date',
'number_people' => 'required',
'number_kids' => 'required'
]);
}
public function bookRoom(Request $request){
$validator = Validator::make($request->all(), [
'start_date' => 'required|date|after:yesterday',
'end_date' => 'required|date|after:start_date',
'people' => 'required',
'days_staying' => 'required',
'free_days' => 'required',
'room' => 'required|array',
'roomCost' => 'required|array',
'roomPeople' => 'required|array',
'totalCost' => 'required',
'name' => 'required|string|max:255',
'email' => 'required|email|string|max:255|unique:users',
'password' => 'required|string|min:6|max:255|confirmed'
]);
if ($validator->fails())
{
return redirect()->back()->withErrors($validator)->withInput();
}
}
When I submit the data and it does not validate in 'bookRoom' method the validation sends a get request and not a post request to 'select-room' url and I end up with a MethodNotAllowedHttpException Error.
I am still understanding Laravel is it possible that you cannot have a logical flow where you have a post page which then posts to another post page which if fails on the second post page will result in an error because your routing only allows post methods. Is the Validation functionality that restrictive that you must have a get request as a contingency for errors or is there something I may setup which can replicate the post request in the validation response set?
To answer your question your select-room route method should be any() instead of post() then.
But there is something wrong with your flow. You should have a GET route where you are displaying the select. A POST route where you are processing the POST data and go back to the GET route if you have errors.
Any redirects are performed using GET. Your forms should be rendered as GET methods, and the data submitted as a POST request. So make a new URL using get for the book-room.
Route::post('select-room', ['as'=>'select-room','uses'=>'ClientBookingController#selectRoom']);
Route::get('book-room', ['as'=>'book-room','uses'=>'ClientBookingController#showBookRoom']);
Route::post('book-room', ['as'=>'book-room','uses'=>'ClientBookingController#bookRoom']);
And in your controller-
public function selectRoom(Request $request){
$this->validate($request, [
'start_date' => 'required|date|after:yesterday',
'end_date' => 'required|date|after:start_date',
'number_people' => 'required',
'number_kids' => 'required'
]);
// Validate data
// Persist data ready for displaying book-room using get
return redirect('book-room');
}
public function showBookRoom()
{
return //your new view with post data from previous url
}
public function bookRoom(Request $request){
$validator = Validator::make($request->all(), [
'start_date' => 'required|date|after:yesterday',
'end_date' => 'required|date|after:start_date',
'people' => 'required',
'days_staying' => 'required',
'free_days' => 'required',
'room' => 'required|array',
'roomCost' => 'required|array',
'roomPeople' => 'required|array',
'totalCost' => 'required',
'name' => 'required|string|max:255',
'email' => 'required|email|string|max:255|unique:users',
'password' => 'required|string|min:6|max:255|confirmed'
]);
if ($validator->fails())
{
return redirect()->back()->withErrors($validator)->withInput();
}
}
So, whenever your second post fails, it will redirect to the intermediate URL using GET request. Read this post from Laracast, you will have a better understanding.

Laravel 5.4 sometimes|required validation not raising on "null" input

I'm having a problem validating inputs that are only going to be present sometimes in the Request.
// Controller
public function update(Request $request, User $user)
{
$updateResult = $user->updateUser($request);
return dd($updateResult);
}
// User Model
protected $validation = [
'rules' => [
'email' => [
'sometimes',
'email',
'required',
],
'password' => [
'sometimes',
'min:6',
'required',
],
'first_name' => [
'sometimes',
'required',
],
'last_name' => [
'sometimes',
'required',
],
],
'messages' => [
'email.required' => 'An email is required.',
'email.email' => 'The email must be valid.',
'password.required' => 'A password is required.',
'password.min' => 'Your password must be at least six (6) characters long.',
'first_name.required' => 'Your first name is required.',
'last_name.required' => 'Your last name is required.',
],
];
public function updateUser(Request $request)
{
$validation = Validator::make($request->all(), [
$this->validation['rules'],
$this->validation['messages'],
]);
if ($validation->fails())
{
return $validation;
}
else
{
return "OK";
}
}
So in some update pages $request->all() is only going to have a subset of these fields. However, even a field is present, but the value is null, the required doesn't trigger.
[
'first_name' => null,
'last_name' => 'Davidson',
'job_title' => 'Tech Support',
]
The above request array will return "OK"... If I remove sometimes from the fields, then when a partial input request is sent, it fails saying the fields are required.
I am clearing missing something here, but from reading the docs I thought I'd configured this correctly:
In some situations, you may wish to run validation checks against a
field only if that field is present in the input array. To quickly
accomplish this, add the sometimes rule to your rule list:
$v = Validator::make($data, [
'email' => 'sometimes|required|email', ]);
The problem you are facing is simply due to an error in your call to the validator. The second parameter is not a multidimensional array as you passed. The rules array and the messages array are separate parameters.
$validation = Validator::make($request->all(), [
$this->validation['rules'],
$this->validation['messages'],
]);
Should be replaced by
$validation = Validator::make($request->all(),
$this->validation['rules'], $this->validation['messages']);
In Laravel 5.4 empty strings are converted to Null by the ConvertEmptyStringsToNull middleware... that might cause you some issues...
You should add nullable to all your optional validations...
Hope this helps
'first_name' => [
'sometimes',
'required',
],
Will never work as expected. Sometimes indicates: if something comes, what is the next rule? In this case 'required'. Required what? Change this to:
'first_name' => [
'sometimes',
'required',
'min:1',
],
The null value will still be a null value if no input is given and won't fail. If you want to keep the value of the field in the table for updates, populate the input in the form with it's respected values.
The null value was send as '' and got nulled by the ConvertEmptyStringsToNull::class in the app\Http\kernel.php middleware.

How can I check i 2 fields of a form have the same content using a rule array of laravelcollective/html validator?

I am pretty new in Laravel and I have the following problem.
I have this method that handle the submit of a form:
public function store(Request $request) {
Log::info('store() START');
$data = Input::all();
Log::info('INSERTED DATA: '.implode("|", $data));
$rules = array(
'name' => 'required',
'surname' => 'required',
'login' => 'required',
'email' => 'required|email',
'emailConfirm' => 'required|email',
'pass' => 'required',
'passlConfirm' => 'required',
'g-recaptcha-response' => 'required|captcha',
);
$validator = Validator::make($data, $rules);
if ($validator->fails()){
return Redirect::to('/registration')->withInput()->withErrors($validator);
}
else{
// Do your stuff.
}
}
As you can see it contains a $rules array containing the validation rules.
It works pretty fine but I want also perform the following 2 checks:
The email field have to contains the same text than the emailConfirm field.
The pass field have to contains the same text than the passConfirm field.
Can I implement this kind of check into the $rules array?
Actually Laravel comes with the validation rule called confirmed. You will need to change your fields to email_confirmation and pass_confirmation and add confirmed rule to email and pass fields.
As answered by #Mariusz, Laravel come up with value comparison rule as confirmed rule. To acheive your output you should write,
$rules = array(
'name' => 'required',
'surname' => 'required',
'login' => 'required',
'email' => 'required|confirmed|email',
'pass' => 'required|confirmed',
'g-recaptcha-response' => 'required|captcha',
);
As you have mentioned, you are using laravelcollective/html, then you have to also add following code to generate confirmation fields
echo Form::email("email_confirmation",null, $attributes = []);
echo Form::password("pass_confirmation",null, $attributes = []);

Categories