Validation in Laravel 8 - php

I´m trying to create a personalized request in Laravel 8.
class SendContactFormRequest 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|min:4|max:30',
'email' => 'required|email',
'phone' => 'required|numeric|size:11',
'message' => 'required|min:4|max:400',
];
}
}
In my controller i´m using it to send email.
public function sendContactForm(SendContactFormRequest $request)
{
try {
$data = [
'name' => $request->get('name'),
'email' => $request->get('email'),
'phone' => $request->get('phone'),
'message' => $request->get('message'),
];
// SEND EMAIL
$this->sendNotification($data);
return redirect()
->back()
->with('success', trans('web.'));
} catch (Exception $e) {
return redirect()
->back()
->with('danger', $e->getMessage());
}
}
But always return HTTP ERROR 500 i don´t know what I´m doing wrong... I´m watching any tutorials and any code example, but I don´t know what it´s my problem.
UPDATED
Finally i did this:
firt i´m creating one personalised request:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SendContactFormRequest 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|string|max:20',
'email' => 'required|email|unique:users,email',
'phone' => 'required|numeric|min:10',
'message' => 'required|string|max:400',
];
}
}
in my controller i add use and create object in function:
public function sendContactForm(SendContactFormRequest $request)
{
try{
$data = [
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'message' => $request->message,
];
// SEND EMAIL
$this->sendNotification($data);
return redirect()
->back()
->with('success', trans('web.'));
}catch (Exception $e) {
return redirect()
->back()
->with('danger', $e->getMessage());
}
}
now i´m user $request->variable before i´m using $request->get() i configure my notification and send my email ok.
Now my problem it´s that i tray send my contact form empty, i can´t show messages... But now i can see i my apache log, that i have this:
[
Mon May 03 17:55:48.109395 2021] [php:error] [pid 9796:tid 1216] [client ::1:61899] PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) in C:\\wamp64\\www\\aeveWeb\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Bootstrap\\HandleExceptions.php on line 129, referer: http://aeveweb.local/contact
i incremented this value to 512MB in wampServer but same result. I think that my code not validate my form, but i don´t understand i don´t know that i´m doin wrong
update
function sendNotification
/**
* SEND NOTIFICATION WHEN CONTACT FORM IT´S SEND
*/
public function sendNotification($data)
{
$emailTo = "";
$details = [
'name' => $data["name"],
'email' => $data["email"],
'phone' => $data["phone"],
'message' => $data["message"],
];
Notification::route('mail', $emailTo)->notify(new newMessage($details));
return redirect()->back()->with('success', 'Notificación enviada');
}

i resolve my question with:
$data = [
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'message' => $request->message,
];
$validator = Validator::make($data,[
'name' => 'required|string|min:3|max:125',
'email' => 'required|string|email|max:100',
'phone' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:9',
'message' => 'required|string|max:400'
]);
if ($validator->fails()) {
return back()->withErrors($validator);
}else{
// SEND EMAIL
$this->sendNotification($data);
return redirect()
->back()
->with('success', trans('web.contact_form_send'));
}

Related

Form Request Rule in Laraval 7 Not Working

I'm using laravel 7
I have a Request that I've built but the required rule is not working. Request sends back without any error.
and dd() also not showing request data.
Function:
public function store(StoreRequest $request)
{
dd($request->all());
if (!auth()->user()->can('add-users')) {
abort(401);
}
try {
$userStatus = app(CreateUser::class)->execute($request->all());
if ($userStatus == true) {
return redirect()->back()->with('success', 'User successfully created.');
} else {
return redirect()->back()->with('error', 'Oops Something went wrong!');
}
} catch (\Exception $ex) {
return redirect()->back()->with('error', $ex->getMessage());
}
}
Request Code:
class StoreRequest 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','string','max:255'],
'email' => ['required','string','max:255'],
'password' => 'required',
'organization_id' => 'required'
];
}
}
If I use Illuminate\Http\Request showing the request data but not validating the data.
Any idea?
Please can you try this
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|string|max:255',
'password' => 'required',
'organization_id' => 'required'
];
}

Laravel 5.7 request validation doesn't work as expected

I use Laravel to submit a form. Here is my web.php routes :
Route::middleware(['auth'])->prefix('account')->namespace('Account')->group(function () {
Route::get('informations', 'AccountController#index')->name('account.informations');
Route::post('informations', 'AccountController#update')->name('account.informations.post');
});
My Controller AccountController.php :
/**
* #param UpdateMember $request
* #return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateUser $request)
{
dd($request->all());
$user = User::where('id', Auth::user()->id)
->update($request->all());
return redirect()->route('account.informations');
}
And my UpdateUser.php :
/**
* 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 [
'lastname' => 'required|string|max:255',
'firstname' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users|confirmed',
'password' => 'required|string|min:6|confirmed',
];
}
My problem : when I use UserUpdate $request in my controller, I don't reach the function, the dd($request->all()) is not shown.
But if I replace :
public function update(UpdateUser $request)
By
public function update(Request $request)
My controller is reached. What do I do wrong ?
what about the unique field validation like email because your validation rules returns a error email already exists while updating a existing record. This can be solved as example below
public function rules()
{
$client = Client::find($this->client);
return [
'name' => 'required|string',
'address' => 'required|string',
'gender' => 'required|string',
'dob' => 'required|string',
'phone' => 'required|string',
'email' => 'required|unique:clients,email,' . $client->id,
'password' => 'regex:/^[0-9a-zA-Z]*$/',
'profile-photo' => 'image|mimes:jpg,png,jpeg',
'c_name' => 'nullable|regex:/^[a-zA-Z ]*$/',
'c_address' => 'nullable|regex:/^[a-zA-Z ]*$/',
'c_email' => 'nullable|email|unique:clients,company_email,'. $client->id,
'c_contact' => 'nullable|regex:/^[0-9]*$/',
];
}
In my case, the reason was that I forgt to add "Accept: application/json" in the request header. After adding that header everything worked fine

Send custom response from validator in Laravel

I have a register user route which takes name , email and password. It works perfectly fine if the data is correct i.e. unique email and params are present, but if the user is already registered then Laravel sends auto error message in its own format. I want return format to be consistent in case of success or failure.
Successful Register return data:
{
"status": "success",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9hcGkvYXV0aC9yZWdpc3RlciIsImlhdCI6MTUyMTI3NTc5MiwiZXhwIjoxNTIxMjc5MzkyLCJuYmYiOjE1MjEyNzU3OTIsImp0aSI6Ik1wSzJSYmZYU1dobU5UR0gifQ.fdajaDooBTwP-GRlFmAu1gtC7_3U4ygD1TSBIqdPHf0"
}
But in case of error it sends data in other format.
{"message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
I want both of them to be consistent. Success return data is fine. But i want to customize data if failure occurs. Something like this:
{"status":"error","message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
Basically, I need status param to be coming with every response.
Also, I had one query while using Postman the output was pure HTML when error occurred the HTML page was default Laravel Page on the other hand when angular sends the same request the error is json format which i just pasted above.
Since angular is getting JSON respose in any case it is fine for me. But why didn't postman showed me that response.
Register Controller:
public function register(RegisterRequest $request)
{
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
Register Request Handler:
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
}
If I understand you correctly, you always get the error-response without the 'status' key.
What happens with your current code, are a couple of things:
RegisterController#register(RegisterRequest $request) is called by a route
Laravel sees you use the RegisterRequest class as an argument, and will instantiate this class for you.
Instantiating this class means it will directly validates the rules.
If the rules are not met, laravel directly responds with the errors found.
This response will always be in laravel's default 'layout' and the code stops there.
Conclusion: Your code is not even triggered when your validation rules are not met.
I've looked into a solution and came up with this:
public function register(Illuminate\Http\Request $request)
{
//Define your validation rules here.
$rules = [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
//Create a validator, unlike $this->validate(), this does not automatically redirect on failure, leaving the final control to you :)
$validated = Illuminate\Support\Facades\Validator::make($request->all(), $rules);
//Check if the validation failed, return your custom formatted code here.
if($validated->fails())
{
return response()->json(['status' => 'error', 'messages' => 'The given data was invalid.', 'errors' => $validated->errors()]);
}
//If not failed, the code will reach here
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
//This would be your own error response, not linked to validation
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
//All went well
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
Now, not conforming your validation rules still triggers an error, but your error, and not laravel's built-in error :)
I hope it helps!
In Laravel 8 I added my custom invalidJson with the "success": false:
in app/Exceptions/Handler.php:
/**
* Convert a validation exception into a JSON response.
*
* #param \Illuminate\Http\Request $request
* #param \Illuminate\Validation\ValidationException $exception
* #return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'success' => false,
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
}
This is what i came up with:
function validate(array $rules)
{
$validator = Validator::make(request()->all(), $rules);
$errors = (new \Illuminate\Validation\ValidationException($validator))->errors();
if ($validator->fails()) {
throw new \Illuminate\Http\Exceptions\HttpResponseException(response()->json(
[
'status' => false,
'message' => "Some fields are missing!",
'error_code' => 1,
'errors' => $errors,
], \Illuminate\Http\JsonResponse::HTTP_UNPROCESSABLE_ENTITY));
}
}
Create a helper directory (App\Helpers) and add it into a file. don't forget to add that into your composer.json
"autoload": {
"files": [
"app/Helpers/system.php",
],
},
Now you can call validate() in your controllers and get what you want:
validate([
'email' => 'required|email',
'password' => 'required|min:6|max:32',
'remember' => 'nullable|boolean',
'captcha' => 'prod_required|hcaptcha',
]);

REST API, Laravel, Validation

I have a small question. I create simple API using Laravel. When I use validation and if it fails, I got a common message:
{
"result": false,
"message": "The given data failed to pass validation.",
"details": []
}
But how can I get details about which field fails and why like that:
{
"result":false,
"message":"The given data failed to pass validation.",
"details":{
"email":[
"The email field is required."
],
"password":[
"The password must be at least 3 characters."
]
}
}
My code in controller looks like this:
protected function validator(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3',
]);
return $validator;
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id' => 2
]);
}
It is better to handle the validator within the same process, like this:
public function register(Request $request){
$validator = Validator::make($request->all(),[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
if($validator->fails()){
return response()->json([
"error" => 'validation_error',
"message" => $validator->errors(),
], 422);
}
$request->merge(['password' => Hash::make($request->password)]);
try{
$user = User::create($request->all());
return response()->json(['status','registered successfully'],200);
}
catch(Exception $e){
return response()->json([
"error" => "could_not_register",
"message" => "Unable to register user"
], 400);
}
}
You should make sure you're sending the request with the Accept: application/json header.
Without that - Laravel won't detect that it's an API request,
If validation fails, a redirect response will be generated 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.
check the documentation
I used validate in my project:
1.I created app/http/requests/CreateUserRequestForm.php
public function rules()
{
return [
"name" => 'required',
"address" => 'required',
"phnumber" => 'required|numeric',
];
}
public function messages()
{
return [
'name.required' => 'Please Enter Name',
'addresss.required' => 'Please Enter Address',
'phnumber.required' => 'Please Enter PhNumber'
];
}
call the RequestForm in controller
use App\Http\Requests\CreateUserRequestForm;
public function createUser(CreateUserRequestForm $request)
{
// create
$user= UserModel::create([
'name' => $request->input('name'),
'address' => $request->input('address'),
'phnumber' => $request->input('phnumber')
]);
return response()->json(['User' => $user]);
}
Try this i didn't try but it should be work for you.
You may use the withValidator method. This method receives the fully
constructed validator, allowing you to call any of its methods before
the validation rules are actually evaluated.
take reference from here. laravel validation
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('email', 'Please enter valid email id');
}
});
}
Try this:
public function create(){
// ------ Validate -----
$this->vallidate($request,[
'enter code here`name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3'
]);
// ------ Create user -----
$user = User::create(['name' => $request->name']);
return response()->json([
'message' => "success",
'data' => $user``
]);
}

Custom Laravel validation messages

I'm trying to create customized messages for validation in Laravel 5. Here is what I have tried so far:
$messages = [
'required' => 'Harap bagian :attribute di isi.',
'unique' => ':attribute sudah digunakan',
];
$validator = Validator::make($request->all(), [
'username' => array('required','unique:Userlogin,username'),
'password' => 'required',
'email' => array('required','unique:Userlogin,email'),$messages
]);
if ($validator->fails()) {
return redirect('/')
->withErrors($validator) // send back all errors to the login form
->withInput();
} else {
return redirect('/')
->with('status', 'Kami sudah mengirimkan email, silahkan di konfirmasi');
}
But it's not working. The message is still the same as the default one. How can I fix this, so that I can use my custom messages?
Laravel 5.7.*
Also You can try something like this. For me is the easiest way to make custom messages in methods when you want to validate requests:
public function store()
{
request()->validate([
'file' => 'required',
'type' => 'required'
],
[
'file.required' => 'You have to choose the file!',
'type.required' => 'You have to choose type of the file!'
]);
}
If you use $this->validate() simplest one, then you should write code something like this..
$rules = [
'name' => 'required',
'email' => 'required|email',
'message' => 'required|max:250',
];
$customMessages = [
'required' => 'The :attribute field is required.'
];
$this->validate($request, $rules, $customMessages);
You can provide custom message like :
$rules = array(
'URL' => 'required|url'
);
$messages = array(
'URL.required' => 'URL is required.'
);
$validator = Validator::make( $request->all(), $rules, $messages );
if ( $validator->fails() )
{
return [
'success' => 0,
'message' => $validator->errors()->first()
];
}
or
The way you have tried, you missed Validator::replacer(), to replace the :variable
Validator::replacer('custom_validation_rule', function($message, $attribute, $rule, $parameters){
return str_replace(':foo', $parameters[0], $message);
});
You can read more from here and replacer from here
For Laravel 8.x, 7.x, 6.x
With the custom rule defined, you might use it in your controller validation like so :
$validatedData = $request->validate([
'f_name' => 'required|min:8',
'l_name' => 'required',
],
[
'f_name.required'=> 'Your First Name is Required', // custom message
'f_name.min'=> 'First Name Should be Minimum of 8 Character', // custom message
'l_name.required'=> 'Your Last Name is Required' // custom message
]
);
For localization you can use :
['f_name.required'=> trans('user.your first name is required'],
Hope this helps...
$rules = [
'username' => 'required,unique:Userlogin,username',
'password' => 'required',
'email' => 'required,unique:Userlogin,email'
];
$messages = [
'required' => 'The :attribute field is required.',
'unique' => ':attribute is already used'
];
$request->validate($rules,$messages);
//only if validation success code below will be executed
//Here is the shortest way of doing it.
$request->validate([
'username' => 'required|unique:Userlogin,username',
'password' => 'required',
'email' => 'required|unique:Userlogin,email'
],
[
'required' => 'The :attribute field is required.',
'unique' => ':attribute is already used'
]);
//The code below will be executed only if validation is correct.
run below command to create a custom rule on Laravel
ı assuming that name is CustomRule
php artisan make:rule CustomRule
and as a result, the command was created such as PHP code
if required keyword hasn't on Rules,That rule will not work
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class CustomRule implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
//return true or false
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The validation error message.';
}
}
and came time using that
first, we should create a request class if we have not
php artisan make:request CustomRequest
CustomRequest.php
<?php
namespace App\Http\Requests\Payment;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class CustomRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
return [
'custom' => ['required', new CustomRule()],
];
}
/**
* #return array|string[]
*/
public function messages(): array
{
return [
'custom.required' => ':attribute can not be empty.',
];
}
}
and on your controller, you should inject custom requests to the controller
your controller method
class FooController
{
public function bar(CustomRequest $request)
{
}
}
You can also use the methods setAttributeNames() and setCustomMessages(),
like this:
$validation = Validator::make($this->input, static::$rules);
$attributeNames = array(
'email' => 'E-mail',
'password' => 'Password'
);
$messages = [
'email.exists' => 'No user was found with this e-mail address'
];
$validation->setAttributeNames($attributeNames);
$validation->setCustomMessages($messages);
For those who didn't get this issue resolve (tested on Laravel 8.x):
$validated = Validator::make($request->all(),[
'code' => 'required|numeric'
],
[
'code.required'=> 'Code is Required', // custom message
'code.numeric'=> 'Code must be Number', // custom message
]
);
//Check the validation
if ($validated->fails())
{
return $validated->errors();
}
$rules = [
'name' => 'required',
'email' => 'required|email',
'message' => 'required|max:250',
];
$customMessages = [
'required' => 'The :attribute field is required.',
'max' => 'The :attribute field is may not be greater than :max.'
];
$this->validate($request, $rules, $customMessages);
In the case you are using Request as a separate file:
public function rules()
{
return [
'preparation_method' => 'required|string',
];
}
public function messages()
{
return [
'preparation_method.required' => 'Description is required',
];
}
Tested out in Laravel 6+
you can customise the message for different scenarios based on the request.
Just return a different message with a conditional.
<?php
namespace App\Rules;
use App\Helpers\QueryBuilderHelper;
use App\Models\Product;
use Illuminate\Contracts\Validation\Rule;
class ProductIsUnique implements Rule
{
private array $attributes;
private bool $hasAttributes;
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct(array $attributes)
{
$this->attributes = $attributes;
$this->hasAttributes = true;
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
$brandAttributeOptions = collect($this->attributes['relationships']['brand-attribute-options']['data'])->pluck('id');
$query = Product::query();
$query->when($brandAttributeOptions->isEmpty(), function ($query) use ($value) {
$query->where('name', $value);
$this->hasAttributes = false;
});
return !$query->exists();
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return ($this->hasAttributes) ? 'The Selected attributes & Product Name are not unique' : 'Product Name is not unique';
}
}
Laravel 10.x
If you are using Form Requests, add another method called messages(): array in your request.
class YourRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required',
'email' => 'required|email',
...
];
}
//Add the following method
public function messages(): array
{
return [
'email.required' => 'Custom message for Email Required',
];
}
}
Then the message will be displayed automatically once the request is send from the form.

Categories