Laravel5 - Request validation always passes - php

I am learning/using Laravel5 and using the Request generator tool to make a custom request validation handler;
php artisan make:request <nameOfRequestFile>
And I find that my validation always passes, but I don't know why.
On my view I do a vardump of the errors;
{{ var_dump($errors) }}
And when I submit an empty form it always inserts a new record, when it should fail.
The var dump reports;
object(Illuminate\Support\ViewErrorBag)#135 (1) { ["bags":protected]=> array(0) { } }
Which seems to suggest the error bag is always empty.
My request file is pretty simple
namespace App\Http\Requests;
use App\Http\Requests\Request;
class PublishDriverRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name.required|min:3' => 'Please provide a name.',
'companyName.required|min:3' => 'Please provide a company name.'
];
}
}
I checked my input form and the names are the same;
<input type="text" name="name" id="name" class="form-control">
<input type="text" name="companyName" id="companyName" class="form-control">
And I checked my database, the names are the same too.
My controller when storing the data is equally straight forward;
public function store(PublishDriverRequest $request) {
Driver::create($request->all());
return redirect('/');
}
So I'm not sure why the validation always passes; if I submit an empty form it should fail as the rules indicate minimum length and required.
What am I doing wrong?

Change you validation rules to:
public function rules()
{
return [
'name' => 'required|min:3',
'companyName' => 'required|min:3',
];
}
To show custom validation error:
public function messages()
{
return [
'name.required' => 'Please provide a name.',
'companyName.required' => 'Please provide a company name.',
];
}
Note: Use message() method before rules()

Related

Validation errors not sent using redirect withInput()

I'm trying to send my validation errors to another method by using redirect
public function save()
{
//validasi input
if (!$this->validate([
'judul' => 'required|is_unique[komik.judul]'
])) {
return redirect()->to('/komik/create')->withInput();
}
this is the create() method
public function create()
{
session();
$data = [
'title' => 'Form Tambah Data Komik',
'validation' => \Config\Services::validation()
];
return view('komik/create', $data);
}
This is a snippet of my create.php view form where I'm trying to validate
<form action="/komik/save" method="post" enctype="multipart/form-data">
<?php d($validation) ?>
<?= $validation->listErrors();; ?>
this is the form
The problem is that the validation errors in save() is not sent to the create() method. But the validation errors exist in the save() method which I can prove by adding
$validation = \Config\Services::validation(); dd($validation);
in save(). This is what happens when I click "Tambah Data" button after I add the code
as you can see there is a validation error, it's just not sent to the create() method
I tried using return view(), this works but it creates another problem. I would like to use return redirect() instead.
This is my routes
$routes->get('/', 'Pages::index');
$routes->get('/komik/create', 'Komik::create');
$routes->get('/komik/edit/(:segment)', 'Komik::edit/$1');
$routes->post('/komik/save', 'Komik::save');
$routes->delete('/komik/(:num)', 'Komik::delete/$1');
$routes->get('/komik/(:any)', 'Komik::detail/$1');
What can I do to solve this problem? Thanks
A. Use Flashdata instead.
CodeIgniter supports “flashdata”, or session data that will only be
available for the next request, and is then automatically cleared.
I.e:
save() method.
public function save()
{
//validasi input
if (!$this->validate([
'judul' => 'required|is_unique[komik.judul]'
])) {
$validation = \Config\Services::validation();
return redirect()
->to('/komik/create')
->with("redirectedErrors", $validation->listErrors())
->with("redirectedInput", $this->request->getVar());
}
}
with()
Adds a key and message to the session as Flashdata.
public with(string $key, array<string|int, mixed>|string $message) : $this
B. Then, modify the create() method to pass on the flashed data to the View.
create() method.
public function create()
{
return view('komik/create', [
'title' => 'Form Tambah Data Komik',
'validation' => \Config\Services::validation(),
'redirectedErrors' => session()->getFlashdata("redirectedErrors") ?: "",
'redirectedInput' => session()->getFlashdata("redirectedInput") ?? [],
]);
}
C. Lastly, in your View file (create.php), you may access the passed-on data normally.
create.php View file.
<form action="/komik/save" method="post" enctype="multipart/form-data">
<?php echo empty($validation->getErrors()) ? $redirectedErrors : $validation->listErrors() ?>
<input id="first_name" name="first_name" type="text" value="<?php echo old('first_name', array_key_exists('first_name', $redirectedInput) ? $redirectedInput['first_name'] : '') ?>"/>
</form>
I found the solution, apparently there's a bug with redirect()->withInput() in CI. You need to use validation_errors(), validation_list_errors() and validation_show_error() to display validation error. Also you don't need to write $validation = \Config\Services::validation();.
Read https://codeigniter4.github.io/CodeIgniter4/installation/upgrade_430.html#redirect-withinput-and-validation-errors

LARAVEL - Form validation return back to view instead of returning JSON?

I don't remember this is always been so freakin' hard to do in Laravel, but how to return back to form page blade.php instead of displaying the errors as JSON object on the browser?
Controller
public function create()
{
return view('view.to.form');
}
public function store(CreateModelRequest $request)
{
Model::create($request->validated());
}
// CreateModelRequest
protected function failedValidation(Validator $validator)
{
return back()->withErrors($validator);
}
I've tried countless other "solutions" as well, but no matter what,
the failed form request return raw JSON to the browser:
{
message: 'The given data was invalid',
errors: {
first_name: ['The first name field is required.'],
last_name: ['The last name field is required.'],
email: ['The email field is required.'],
},
}
}
Ok, I found one way to return back to the form but damn this is awful:
// Controller's store method
$validator = Validator::make($request->all(), [
// rules
]);
if ($validator->fails()) {
return back()->withErrors($validator->errors());
}
I'd like to extract that code into Request class but apparently we can't return a view and therefore we can't use them outside of API endpoints. Please, correct me if I'm wrong.

How to apply validation on any single field having same name Laravel?

I have a project that consists of multilingual functionality. So I'm creating a form that consists of multiple languages to be inserted if User wants.
But validation should be like if any of the fields having the same name consist value then leave rest one like as
Form
<form>
<input type="text" name="name[EN]" />
<input type="text" name="name[AR]" />
<input type="text" name="name[FR]" />
<input type="submit" value="submit" />
</form>
Now I want to validate that if any one of these fields have value then submit form else throw a validation
So I've tried Laravels required_if, but it didn't work.
public function rules()
{
return [
'name.*' => 'required_if:name,1',
];
}
So how to make such validation in laravel
I've searched but could not find a built in way of doing this. You can create your own rule using
php artisan make:rule NonEmptyFiltered
and then define the rule as:
class NotEmptyFiltered implements Rule {
public function passes($attribute, $value) {
return !empty(array_filter($value));
}
public function message() {
return ':attribute must have at least one non-null element';
}
}
You can then do:
public function rules()
{
return [
'name' => [ new NonEmptyFiltered() ]
];
}
I believe this should do the trick:
$rules = [
'name.EN' => 'required_without_all:name.AR,name.FR',
'name.AR' => 'required_without_all:name.EN,name.FR',
'name.FR' => 'required_without_all:name.EN,name.AR',
];
The rule makes the field to be required if the other fields are empty https://laravel.com/docs/5.6/validation#rule-required-without-all.

Use Laravel 5 Form Request validation with related models

I'm using (and loving) the Laravel 5 form request validation so far. But now I'm stuck trying to validate related models.
Say I have a Car model which has many Wheel models and I'd like to validate a new car. In the CarController#store method I'm using the following to validate the car, but this does of course not validate the wheels.
public function store(StoreCarRequest $request)
{
// Create the car
}
What needs to be done to validate the Wheels of a Car? Can this be done with form request validation?
Edit
I'm getting closer. The remaining issue is that I need to iterate through the wheels which are stored in an array (because the HTML input name is e.g. wheels[0][color]), but the validator is searching for a color field, not wheels[0][color].
public function store(StoreCarRequest $r)
{
// Validate the wheels
foreach ($r->input('wheels') as $wheel)
{
// TODO: use $wheel somewhere?
$snr = new StoreWheelRequest;
$this->validate($r, $snr->rules()); // Validation fails: 'color' field is required
}
// Validation passed, create the car (and the wheels)
}
StoreCarRequest.php
public function rules()
{
return [
'engine' => 'required',
'seats' => 'required',
];
}
StoreWheelRequest.php
public function rules()
{
return [
'color' => 'required',
];
}
The HTML form
<form method="POST" action="...">
<input type="text" name="engine">
<input type="text" name="seats">
<input type="text" name="wheels[0][color]">
<input type="text" name="wheels[1][color]">
<input type="text" name="wheels[2][color]">
<input type="text" name="wheels[3][color]">
<input type="submit" value="Create">
</form>
After some more Googling, I stumbled upon the following article: http://ericlbarnes.com/laravel-array-validation/
It boils down to adding rules dynamically inside the rules() method by iterating over the input array.
You can use dot notation to validate nested arrays :
public function rules()
{
return [
'engine' => 'required',
'seats' => 'required',
'wheel.color' => 'required',
];
}

Laravel - same custom error message for multiple fields

Im using a form request for validation and want to customize my errors. since I have a lot of fields to validate,I want to know if it is possible to use the same error message for multiple fields that have the same validation rule.
My actual form request looks like :
class CreateServerRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'srv_prefix' => 'required|regex:/^[A-Z][-_A-Z0-9]*$/',
//20 more to go...
];
}
public function messages()
{
return [
'srv_prefix.required' => 'required.',
'srv_prefix.regex' => 'nope, bad format.'
];
}
}
I dont like the idea of adding as many lines of errors as fields (some fields may have 2 validation rules..) is there any way to tell laravel if validation rule = required then show this type of error regardless of the field ?
You can use just the validation name as the key for the message array, if you want all messages for that particular validation to be the same:
public function messages()
{
return [
'required' => 'The field :attribute is required.',
'regex' => 'nope, bad format.'
];
}
You can use :attribute as a placeholder that will be replaced with the field name, if you need that to be part of the error message. The documentation for this is in the Validation Custom Error Messages section, not in the Form Request Validation one.

Categories