How to solve above issue? I want to keep test even after a validation failure in the submission. But after session error message is passed all the entered data will be gone.
To re-fill the form with the input data again, check the input validation then if validation fails, redirect the user back along with his input data and validation errors.
$validator = Validator::make($request->all(), [
// your validation rules.
'name' => 'required',
]);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}
// Continue your app logic.
You'll find more information in Laravel validation docs
You should send back the input also to the view.
Like Sameh Salama already mentioned, use the following code:
function () {
return redirect()->back()->withErrors($validator)->withInput();
}
Notice the withInput() function, it returns the old input.
Use it in the View as
<input type="something" value="{{$input->first_something}}" />
Related
I've done this thousands of times on past projects, but I feel since moving to laravel 8 on our latest application something has changed.
I used to be able to do something as simple as:
$response = $this->post('/api/team', []);
$response->assertJsonFragment([
"The team name field is required."
]);
However when running the test I get the following error:
1) Tests\Feature\Controllers\Team\CreateTest::teamNameRequired
Unable to find JSON fragment:
[["The team name field is required."]]
within
[["{\"team_name\":[\"The team name field is required.\"]}"]].
Failed asserting that false is true.
I've tried swapping to assertJson and a couple others but ideally this is how I'd like to assert, I also could create a separate function or use some other helpers but I want to assert not just that there has been a validation error, but a specific one.
I'm using the standard laravel validator and response object for context:
$validator = Validator::make($request->all(), [
'name' => 'required|string|between:2,100'
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
This was caused because I was json encoding the errors twice.
Within my controller the following if statement should have been used:
if($validator->fails()){
return response()->json($validator->errors(), 400);
}
//TestRequest.php
public function rules()
{
return [
'name' => 'string|required|min:5',
'tip' => 'string|required|min:5',
'answer' => 'string|required',
'image' => 'file|required|mimes:png,jpg,jpeg'
];
}
//TestController.php
public function put(TestRequest $request)
{
$validated = $request->validated();
}
I'm doing some rest API. I need a form with some text fields and one image upload field but I have a problem with validating it.
When I'm sending the request as 'form-data' in the Postman, Laravel doesn't see in the validation any fields (why?).
When I'm sending the request as application/x-www-form-urlencoded Laravel sees my text fields, but I can't, of course, upload the image.
API will be used by the android APP. How I can solve this? How I can have both validation on text and file inputs?
Using application/x-www-form-urlencoded is the correct way to upload images. According to your second screenshot, you are not sending the file field in Postman, but you are sending it in the first screenshot.
see this
'name' => 'string|required|min:5',
minimum is 5 character but you send test or 4 chars. Laravel validation rule, if it failed it will stop or next validation will not checked.
I think I've found a solution.
Changing method from PUT to POST seems to fix this issue.
I do have a registration form in my laravel 5.4 application and laravel form request validation is used for server side validation. Some fields in this form are populated dynamically using calculations in javascript which need to be validated against user inputs.
The user input fields in the form are 'quantity', 'rate' and 'discount'.
The populated fields are 'total' and 'bill_amount'.
What i need to validate are :
Check 'total' equal to 'quantity' * 'rate'.
Check 'bill_amount' equal to 'total' - 'rate'
I would prefer laravel form request validation methods for this validation. I have tried to use methods like After Hooks and conditionally adding rule etc. and failed.
In simple words the requirement is : check if a field is equal to product of other two fields, and invalidate if not equal and validate if equal.(using form request validation.)
Thanks in advance!
After a long time I was able to find this solution.
Form request After Hooks can be used to achieve the result:
[I was unable to find this logic before]
public function withValidator($validator)
{
$quanty = $this->request->get("quantity");
$rate = $this->request->get("rate");
$billAmount = $this->request->get("bill_amount");
$validator->after(function ($validator) {
if(($quanty * $rate) != $billAmount) {
$validator->errors()->add('bill_amount', 'Something went wrong with this field!');
}
});
}
What basically is the difference between Controller and Routes. We can control our data using routes file, then why do we need controllers?
Like:
<?php
// app/routes.php
// route to process the ducks form
Route::post('ducks', function()
{
// process the form here
// create the validation rules ------------------------
$rules = array(
'name' => 'required', // just a normal required validation
'email' => 'required|email|unique:ducks', // required and must be unique in the ducks table
'password' => 'required',
'password_confirm' => 'required|same:password' // required and has to match the password field
);
// do the validation ----------------------------------
// validate against the inputs from our form
$validator = Validator::make(Input::all(), $rules);
// check if the validator failed -----------------------
if ($validator->fails()) {
// get the error messages from the validator
$messages = $validator->messages();
// redirect our user back to the form with the errors from the validator
return Redirect::to('ducks')
->withErrors($validator);
} else {
// validation successful ---------------------------
// our duck has passed all tests!
// let him enter the database
// create the data for our duck
$duck = new Duck;
$duck->name = Input::get('name');
$duck->email = Input::get('email');
$duck->password = Hash::make(Input::get('password'));
// save our duck
$duck->save();
// redirect ----------------------------------------
// redirect our user back to the form so they can do it all over again
return Redirect::to('ducks');
}
});
Well, this is not my code, I read it somewhere, But, here this person has used the validation in routes.php file, and in my project, I used the validation technique in a controller named UserController, what difference does it make?
Routes translate each incoming HTTP request to an action call, for example to a method of a controller, whereas controller is the place where business logic are written. There is nothing wrong in handling all in one file, but once your projects gets bigger it would be nightmare to manage such code. It's like responsibility, route, route the request to specific controller, controller process it, pass result to view. Mostly it's design pattern.
We can even have all the code in one huge file without using any classes at all, but we know that is not a good idea. The current best practice is to separate the code depending on responsibilities (single responsibility principle) to make it easier to other developers to read and understand the code. Often the next developer is yourself in some months, so having a clean structure don't only benefit others but also your sanity when going back to your old code.
The name router imply that the class routs data, in this case from an URI to a controller and the controller handle the business rules for that particular controller
Routes in laravel is a place where you define your application end points and controller is where you write your business logic.
I had the same problem understanding Laravel when I started to learn and to make it simple, I have created some project in MCV style please check this
https://github.com/jagadeshanh/understanding-laravel
I have a form. When validation fails i redirect to the same page. "mobilepage1.blade.php"
But all my entries are all gone. I want all my entries to stay. Exept the password.
I redirect my page with View::make
return View::make('mobilepages.mobilepage1', array('errormessages' => 'errormessages'));
I use:
$input = Input::all();
to get the input.
All input
return Redirect::to('mobilepages')->withInput(Input::all());
Except password
return Redirect::to('mobilepages')->withInput(Input::except('password'));
Old Input
In your form view, use something like this for the inputs:
<?= Form::text('title', (Input::get('title') ?: NULL)); ?>
The (Input::get('title') ?: NULL) operator will return the previous title value if it was set and nothing if it wasn't set.
It should be done using something like this:
public formSubmitMethod() // Change formSubmitMethod with appropriate one
{
// This is the form submit handler
// Set rules and validate the inputs
$rules = array(...); // set rules here but there are other ways
$inputs = Input::except('_token'); // everything but _token
$validatior = Validator::make($input, $rules);
if($validatior->fails()) {
// Validation failed
return Redirect::back()->withInput()->withErrors($validatior);
}
else {
// Success
// Do whatever you want to do
}
}
In your form, use Input::old('fieldname'), something like this:
{{ Form::input('username', Input::old('fieldname')) }}
That's it, now if you redirect back for invalid user inputs then your form fields will be repopulated with old values. Don't use old() method in the password field. You can also access the error message for a field using something like {{ $errors->first('username') }}, so if this (username) field invalidated then the error message for this field will be printed out.
Also, notice that, to redirect back, I've use Redirect::back() not View::make(), it's (make) not for redirecting but for rendering a view to show it.