I am using FormRequest to do my validations. I am trying to set a top-level error message via Flash to show to the user that the form submission did not succeed.
Right now I have the following UserResquest
class UserRequest extends FormRequest {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'required|string|min:2|max:50',
'last_name' => 'required|string|min:2|max:50',
'date_of_birth' => 'required|date',
'gender' => 'required|in:male,female'
];
}
I am trying to do this in my Controller
$validator = $request->validated();
if ($validator->fails()) {
Session::flash('error', $validator->messages()->first());
return redirect()->back()->withInput();
}
But the Flash message is turning up empty. whats the best way to set the Flash Error message when using FormRequest
Am setting my Flash Message as following the View Template.
<div class="flash-message">
#foreach (['danger', 'warning', 'success', 'info'] as $msg)
#if(Session::has('alert-' . $msg))
<p class="alert alert-{{ $msg }}">{{ Session::get('alert-' . $msg) }} ×</p>
#endif
#endforeach
</div> <!-- end .flash-message -->
FormRequest does it automatically, you dont have to handle it in the controller.
it does so in
protected function failedValidation(Validator $validator)
{
throw (new ValidationException($validator))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
}
You can overload the method if you want another behavior.
To get the error messages, you need to fetch it in the error bag
{{ $errors->default->first('first_name') }}
the error bag is named default by default, you can change it in your FormRequest extended class
Custom messages
To set the message per error, declare the following method in your UserRequest class
public function messages()
{
return [
'first_name.required' => 'A first name is required',
'first_name.min' => 'The first name can\'t be a single character',
...
];
}
And to know if there are errors, check the variable $errors->default in your blade then you can show the message "The Form did not save. Check below for the error and try again"
As N69S pointed out. We can set it under failedValidation as below.
/**
* Handle a failed validation attempt.
*/
protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{
session()->flash('alert-danger', 'There was an error, Please try again!');
return parent::failedValidation($validator);
}
Related
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The GET method is not supported for this route. Supported methods: POST.
Validation is working but the data is not being saved in array or something like that because i am unable to pass the data into view.
+My SendEmailConroller.php consists of:
class SendEmailController extends Controller
{
public function send(Request $request)
{
$this->validate($request,[
'email' => 'required|email',
'phone' => 'required|min:10|max:10',
'messagefor' =>'required|min:5'
]);
$data =array(
'name' => $request->email,
'email' => $request->email,
'phone' => $request->phone,
'messagefor' => $request->messagefor
);
Mail::to('shishir.nepal.9#gmail.com')->send(new WelcomeMail($data));
return back()->with('success','Thank you for contacting us');
// return redirect()->to('/email')->with($data);
}
public function index(){
return view('emails.welcome')
}
+I am trying to Send data from form to email controller and then show in welcome.blade.php
+My Welcome mail consists of:
class WelcomeMail extends Mailable
{
use Queueable, SerializesModels;
public $data;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($data)
{
$this->data =$data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('help#gmail.com')->subject('new seo for my page')->markdown('emails.welcome')->with('data',$this->data);
}
}
And my web.php is:
Route::post('/email','SendEmailController#send');
Route::get('/sendemail','SendEmailController#index');
And at last my welcome.blade.php
#if($message=Session::get('success'))
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">x</button>
<strong>{{$message}}</strong>
</div>
#endif
<p>Hi , This is {{$data['name']}}</p>
<p>I have some query like" {{$data['messagefor']}} "</p>
I'm using a custom request class for laravel form validations.
This is my request class
class ContactUsRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'lname' => 'required'
];
}
/**
* Get the error messages for the defined validation rules.
*
* #return array
*/
public function messages()
{
return [
'lname.required' => 'please enter the last name'
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
}
And this is where I call it,
public function send(ContactUsRequest $request) {
$validator = $request->validated();
if ($validator->fails()) {
return redirect('/contactus')
->withErrors($validator)
->withInput();
} else {
ContactUs::create($request->all());
return redirect('/contactus');
}
}
But when I input correct values I get this,
Symfony \ Component \ Debug \ Exception \ FatalThrowableError
(E_ERROR) Call to a member function fails() on array
That's because request object automatically do that for you and you don't need to redirect back manually and $validator variable contains validated inputs so in your case you don't need to do anything and you can remove if and redirect safely
public function send(ContactUsRequest $request) {
ContactUs::create($request->validated());
return redirect('/contactus');
}
}
Using form request classes
If validation fails, a redirect response will be generated automatically to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
In order to capture validation failure you may use the Validator facade
E.g
use Illuminate\Support\Facades\Validator;
//...
public function send(Request $request) {
$validator = Validator::make($request->all(), [
'lname' => 'required'
// ...
]);
if ($validator->fails()) {
return redirect('/contactus')
->withErrors($validator)
->withInput();
}
ContactUs::create($request->all());
return redirect('/contactus');
}
Form Request Validation Documentation
Manually Creating Validators Documentation
And we can keep ContactUsRequest like this.
public function send(ContactUsRequest $request) {
$validator = $request->validated();
ContactUs::create($request->all());
return redirect('/contactus');
}
I am attempting to set and pass a flash message, when a form validation fails. When the validation passes, I am able to set Flash message in the controller.
I have tried to override the protected failedValidation() but I get an error.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Validator;
class UserRequest extends FormRequest {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'required|string|min:2|max:50',
'last_name' => 'required|string|min:2|max:50',
'date_of_birth' => 'required|date',
'gender' => 'required|in:male,female'
];
}
/**
* Handle a failed validation attempt.
*/
protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{
Flash::error("Profile could not be saved!");
// alert()->error('oops ... error');
return parent::failedValidation($validator);
} }
error:
Symfony\Component\Debug\Exception\FatalThrowableError Class
'App\Http\Requests\Flash' not found
I am setting my view in app.blade.php as follows
<div class="flash-message">
#foreach (['danger', 'warning', 'success', 'info'] as $msg)
#if(Session::has('alert-' . $msg))
<p class="alert alert-{{ $msg }}">{{ Session::get('alert-' . $msg) }} ×</p>
#endif
#endforeach
</div> <!-- end .flash-message -->
you need to add use Flash; in the controller at the top after namespace declaration where you want to use the flash library methods.
I'd like to validate a form using both custom messages and attributes. Instead of name: The name may not be greater than 20 characters. the user should see Name: Please use fewer characters., for example.
I'm using AJAX and both keys and values of the response.data.errors object that Laravel returns. Im using Laravel 5.7.
This is a simplified version of the validator function in my RegisterController.
protected function validator(array $data)
{
// Nice attribute names
$attributes = [
'name' => 'Name',
// ...
];
// Custom messages
$messages = [
'max' => 'Please use fewer characters.'
// ...
];
// Rules
$rules = [
'name'=> 'required|max:20',
// ...
];
// Working for messages, but not for attribute names
$validator = Validator::make($data, $rules, $messages, $attributes);
// Also not working
// $validator->setAttributeNames($attributes);
return $validator;
}
When there's a validation error, the user get's a message like name: Please use fewer characters.. That means the message from my custom array is displayed, but the default attribute name is used. What's wrong here?
Attributes do not replace key names, they are used to change the appearance of a key within a message - i.e The Name field is required - to achieve what you're trying to do in your question you'll need to create a new data array.
protected function validator(array $data)
{
$data = [
'Name' => $data['name'] ?? '',
// ...
];
// ...
Validator::make($data, $rules, $messages);
}
use Laravel Form Request, scroll down to Customizing The Error Messages section. Check out the below sample code.
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UserRegistrationForm extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|max:20',
];
}
/**
* Get the error messages for the defined validation rules.
*
* #return array
*/
public function messages()
{
return [
'name.max' => 'Please use less characters'
];
}
}
In controller
public function register(UserRegistrationForm $request)
{
// do saving here
}
That is coming from validation.php located in resources/Lang/xx/
EDIT :
You'll have to use
$messages = [
'name.max' => 'Your sentence here',
];
I am having a problem returning a proper response to an ajax request I made.
Basically, I have a checkbox which when changed() fires an ajax with csrf-token to be accepted in POST method, the changes reflected on the database is successful but the error starts on returning the "status" of the process to the ajax.
Heres my controller method:
public function update(Request $request, $id)
{
$result = ItemPrice::toggleRestockable($id);
return $result;
}
$result is the output of DB::update() method
The ajax goes to error: block with Internal Server Error 500 regardless whether the query was a success or not.
The responseText of data variable in ajax was mainly:
(1/1) UnexpectedValueException
The Response content must be a string or object implementing __toString(), "boolean" given.
Now I know I am returning boolean or technically an integer because it was a result of DB::update() which returns the number of rows affected by the update.
Now how could I properly return a response that an ajax can understand?
Try This
public function update(Request $request, $id)
{
$result = ItemPrice::toggleRestockable($id);
return Response::json(['success' => $result], 200);
}
Create one base ApiController abstract class and extend it in your any controller. so you no need to prepare response obj for success and error in every function and every controller. you just call function. example given here.
// Base ApiController
abstract class ApiController extends Controller
{
/**
* Make standard response with some data
*
* #param object|array $data Data to be send as JSON
* #param int $code optional HTTP response code, default to 200
* #return \Illuminate\Http\JsonResponse
*/
protected function respondWithData($data, $code = 200)
{
return Response::json([
'success' => true,
'data' => $data
], $code);
}
/**
* Make standard successful response ['success' => true, 'message' => $message]
*
* #param string $message Success message
* #param int $code HTTP response code, default to 200
* #return \Illuminate\Http\JsonResponse
*/
protected function respondSuccess($message = 'Done!', $code = 200)
{
return Response::json([
'success' => true,
'message' => $message
], $code);
}
/**
* Make standard response with error ['success' => false, 'message' => $message]
*
* #param string $message Error message
* #param int $code HTTP response code, default to 500
* #return \Illuminate\Http\JsonResponse
*/
protected function respondWithError($message = 'Server error', $code = 500)
{
return Response::json([
'success' => false,
'message' => $message
], $code);
}
How to use functions of base class. see example here
public function update(Request $request, $id)
{
try{
$result = ItemPrice::toggleRestockable($id);
return $this->respondWithData($result);
}catch(Exception $e){
return $this->respondWithError($e->getMessage());
}
}
how to extend base controller into your controller
class TestController extends ApiController {}
JsonResponse is the class you need.
return response()->json($result);
using helpers. Use ->toArray() on $result if dealing with collections.
return $result;
will return the object of data, there are multiple ways to handle this depending on the return type of your toggle function.
The Typical way to handle an AJAX request is to save data and return the status and message.
in your scenario, I could use a response to JSON
public function update(Request $request, $id)
{
$status = 500;
$message = 'An Un expected error Occured';
try {
$result = ItemPrice::toggleRestockable($id);
//assuming toggleRestockable function will return bool
if ($result) {
$status = 200;
$message = 'Successfully Updated';
}
return response()->json(['status' => $status, 'message' => $message]);
} catch (Exception $e) {
return response()->json(['status' => 500, 'message' => $e->getMessage()]);
}
}
This way of doing works fine for me
public function update(Request $request, $id)
{
$this->validate($request, [
//some of your data =>'required|min:4'; <-your rules
]);
$result = ItemPrice::findOrFail($id);
//something request;
$result->save();
return response()->json(['result'=>$result]);
}
and you can call your error by using this
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
i hope it will helps you a lot :)