I have an array with two relevant keys where at least one of both shall contain a valid email address.
$data = [
'mail' => 'firstname.lastname#tld.com',
'mail2' => 'firstname.lastname#tld.com',
...
]
I've tried a validation using the exclude_with method, which works if the mail field is invalid, but mail2 is valid. However, it doesn't vice versa.
$validated = Validator::make($data, [
'mail' => 'exclude_with:mail|email',
'mail2' => 'exclude_with:mail2|email',
])->validate();
I could do this easily with other PHP methods or regular expressions, but I wonder if this is archivable with Laravel's validator.
The goal is to get at least one field with a valid email or fail.
Update
Based on Abdulla's promising answer, I found that even if the first email is valid but the second is not, the validation fails:
$data = [
'mail' => 'firstname.lastname#tld.com', // correct
'mail2' => 'firstname.lastname#tld.com' // wrong
];
$validator = Validator::make($data, [
'mail' => 'exclude_unless:mail2,null|email',
'mail2' => 'exclude_unless:mail,null|email',
]);
Output:
The mail2 must be a valid email address.
Use exclude_unless() in Laravel
It was tested with these two examples. (You can swap array positions too). And removed ->validate() as well
One valid and one invalid Email (as per in the question)
$data = [
'mail' => 'firstname.lastname#tld.com', // wrong
'mail2' => 'firstname.lastname#tld.com' // correct
];
$validator = Validator::make($data, [
'mail' => 'exclude_unless:mail2,null|email',
'mail2' => 'exclude_unless:mail,null|email',
]);
if ($validator->fails()) {
$messages = $validator->messages();
foreach ($messages->all() as $message)
{
echo $message;
}
die();
}
echo "pass";
die();
Output was
Both invalid emails
$data = [
'mail' => 'firstname.lastname#tld.com', // wrong
'mail2' => 'firstname.lastname#tld.com' // wrong
];
$validator = Validator::make($data, [
'mail' => 'exclude_unless:mail2,null|email',
'mail2' => 'exclude_unless:mail,null|email',
]);
if ($validator->fails()) {
$messages = $validator->messages();
foreach ($messages->all() as $message)
{
echo $message;
}
die();
}
echo "pass";
die();
Output
customize the error message to a standard message such as "At least one Email should be valid".
Related
So, I have controller method which validates user and updates their information.
public function updateBasicInfo(Request $request)
{
$basic_info = Validator::make($request->all(), [
'fullname' => 'required|min:2|max:255',
'phone_number' => 'required|numeric|min:10',
'email' => 'required',
'country' => 'required',
'address' => 'required',
], [
'phone_number.min' => "The phone number must be at least 10 digits",
]);
if($basic_info->fails())
{
return response()->json([
'errors'=> $basic_info->errors()->all(),
]);
}
else
{
$basic_info = $basic_info->validated();
$user = request()->session()->get('id');
$currentUser = User::firstWhere('username', $user->username);
$currentUser->name = $basic_info['fullname'];
$currentUser->phone_number = $basic_info['phone_number'];
$currentUser->email = $basic_info['email'];
$currentUser->save();
UserDetail::firstWhere(['username' => $user->username])->update([
'address'=>$basic_info['address'],
'country' => $basic_info['country'],
]);
$current_user = $currentUser;
Mail::to($current_user->email)->send(new ProfileMail($user));
return response()->json(['success'=> 'Profile Updated Sucessfully']);
}
}
I want to update user but I don't want two users to have the same email and I also want the user email to change only if it's value has been changed in the database.
Check to make sure that only the user has that email in the whole table and update it to prevent double email records
Please, how do I do this?
I have tried calling the isDirty() method,nothing seems to work
You can use the unique validation rule for email with ignore to make sure that it doesn't receive an error if the new email is the same as the last email. (Unique validation only in comparison with other users). Check out this link.
$basic_info = Validator::make($request->all(), [
'fullname' => 'required|min:2|max:255',
'phone_number' => 'required|numeric|min:10',
'email' => 'required|unique:users,email,'.request()->session()->get('id'),
'country' => 'required',
'address' => 'required',
], [
'phone_number.min' => "The phone number must be at least 10 digits",
]);
The isDirty() method is to check if you set a value to any of the properties of instance. And it checks the change after it occured.isDirty()
I'm using the Laravel Validator to test my incoming request. So to be sure that the request contains an username and an email, I write something like that:
$validator = Validator::make($request->all(), [
'username' => 'required',
'email' => 'required|email'
]);
if ($validator->fails()) {
return response()->json('error', 400);
};
But if in my request I have an additionnal params like name, the validator will not consider it as an error and will not fail.
Have you an idea how I can make my validator more strict so that the request body match exactly?
Technically it's not a validation fail in the Validator. But you could check if there are extra (unexpected) fields and send a JSON response based on that if you wanted.
Something like this maybe?
$validationRules = [
'username' => 'required',
'email' => 'required|email'
];
$validator = Validator::make($request->all(), $validationRules);
// Check if there are extra (unexpected) fields and fail in that case
$extraFields = $request->except(array_keys($validationRules));
if (count($extraFields) > 0) {
return response()->json('error because there are extra fields', 400);
}
if ($validator->fails()) {
return response()->json('error', 400);
}
return response()->json('ok', 200);
I hope it can help you.
Validation rules can be attached only to properties, so I don't think Laravel's Validator is able to do that. But you still can explicitly forbid certain fields by providing a custom closure rule to them, like this:
$denied = function($attr, $value, $fail) {
$fail("{$attr} is denied.");
};
$validator = Validator::make($request->all(), [
'username' => 'required',
'email' => 'required|email',
'name' => $denied,
'password' => $denied
]);
Otherwise you need to implement custom validation logic, probably utilizing the rule array from your validator as a white list.
I'm using a Class extends Laravel's FormRequest class. I have arrays incoming, so I have rules like:
public function rules()
{
return [
'name' => 'required',
'name.*.value' => 'required',
'email' => 'required',
'email.*.value' => 'required|email',
];
}
Basicly when I do my Ajax call it returns 422 with message for eg:
The name.0.value field is required.
I want it to be something like : The {index}th name is required.
public function messages()
{
return [
'email.*.value.required' => 'Recipient email field is required',
'email.*.value.email' => 'Wrong e-mail format',
];
}
Is there an option to include the * somehow in the message? Or am I supposed to process it with JQuery?
Thanks in advance.
Try to use loop like this:
public function messages() {
$messages = [];
foreach ($this->get('email') as $key => $val) {
$messages["email.$key.value.required"] = "email $key is required";
$messages["email.$key.value.email"] = "email $key is wrong e-mail format";
}
return $messages;
}
I have refactored the code a little bit, to suit my style. It's working like this as well, if someone like this style more. Of course TsaiKoga's answer is flawless, and good to go with it!
public function messages(){
$messages=[];
foreach ($this->get('email') as $key => $val) {
$messages = [
"email.$key.value.required" => "$key th e-mail is required",
"email.$key.value.email" => "$key th e-mail is wrong e-mail format",
"name.$key.value.required" => "$key th name is required"];
}
return $messages;
}
$rules = [
'name' => 'required',
'password' => 'required',
'email' => 'required|email'
];
$validator = Validator::make($request->only('name','password','email'), $rules);
if ($validator->fails()) {
$messages = $validator->errors()->messages();
return response()->json(['status' => 'error', 'messages' => $messages]);}
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``
]);
}
I get the wrong error messages. My purpose is following :
1. checking username / pw combination, and if it doesn't match, "wrong username/pw combination" error through validator.
2. captcha (mews) is troubling me. Even user enters true captcha chars (no case-sensitive by config) I get the error message.
Here is my validator :
FYI: i have a table "user" instead of users, and i can use it nicely in other controllers.
protected function loginValidator()
{
$message = array(
'exists:user,username' => 'Wrong username/pass combination',
'exists' => 'Wrong :attribute.',
'required' => ':attribute cannot be empty',
'captcha' => 'Wrong captcha'
);
return Validator::make(Input::all(),[
'usernameInput' => 'required|exists:user,username',
'passwordInput' => 'required',
'captchaInput' => 'captcha|required'
], $message);
}
Even if username/pass combination is true, i get wrong captcha message.
Thanks in advance.
protected function loginValidator()
{
$validator = Validator::make(
array(
'name' => 'Dayle',
'password' => 'lamepassword',
'email' => 'email#example.com'
),
array(
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
)
);
if ($validator->fails())
{
// The given data did not pass validation
$data['messages'] = $validator->messages()->all();
}
else
{
//complete validation
}
return View::make('home.login', $data);
}