laravel validation check if input value exists in emails or users - laravel

please I want know if there is any method to validate an input if exists in column email or username
without deal with code just validation system in laravel like
'username'=>'required|exists:App\Models\User,email OR exists:App\Models\User,username'
I want to make a 'LOST PASSWORD' like wordpress
wordpress lost password system ask the users for email or username if exits it's okey if it's not display an error message

If you really need to check if the username exists as a users.email or as a users.username, you should make a Custom Validation Rule - since the exists rule can't cover both of these. Something like this should work:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use App\Models\User;
class EmailOrUsername implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return User::where(function($q) use($value) {
$q->orWhere('email', $value)->orWhere('username', $value);
})->count() > 0;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'Sorry, your credentials do not match our records.';
}
}
When you need to use it, you do it like this:
<?php
use App\Rules\EmailOrUsername;
$request->validate([
'username' => ['required', 'string', new EmailOrUsername],
]);

Related

Laravel conditional validation rule for array items

I have the following working validation rule which checks to make sure each recipient,cc,bcc list of emails contain valid email addresses:
return [
'recipients.*' => 'email',
'cc.*' => 'email',
'bcc.*' => 'email',
];
I need to also be able to allow the string ###EMAIL### as well as email validation for each of these rules and struggling to create a custom validation rule in Laravel 5.8 (it can't be upgraded at this time).
Any idea how to go about this? If it were a higher version of Laravel I was thinking something like (not tested) to give you an idea of what I'm trying to do:
return [
'recipients.*' => 'exclude_if:recipients.*,###EMAIL###|email',
'cc.*' => 'exclude_if:recipients.*,###EMAIL###|email',
'bcc.*' => 'exclude_if:recipients.*,###EMAIL###|email',
];
In 5.8 you can create Custom Rule Object Let's see how we can actually make it work.
Create your rule with php artisan make:rule EmailRule
Make it to look like this
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class EmailRule implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
if ($value === '###EMAIL###' or filter_var($value, FILTER_VALIDATE_EMAIL)) {
return true;
}
return false;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be valid email or ###EMAIL###.';
}
}
Include in your rules so it looks like
return [
'recipients.*' => [new EmailRule()],
'cc.*' => [new EmailRule()],
'bcc.*' => [new EmailRule()],
];
Write a test (optional)

Laravel 5 Validation accept comma separated string with max 4 numbers

Laravel 5 Validation accept comma separated string with max 4 numbers
Example-
1. 1,2,3,4 --- Accepted
2. 1,2 --- Accepted
3. 1,2,3,4,5 --- Rejected
Note: I can Achieve this task by first convert the string to array and then validate the request, But i am looking for a Best approach to solve the same.
Validate it with this in your controller:
$this->validate(Request::instance(), ['field_name'=>['required','regex:/^\d+(((,\d+)?,\d+)?,\d+)?$/']]);
You can create your own custom Rule for this.
php artisan make:rule MaxNumbers
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class MaxNumbers implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return count(explode(',', $value)) < 5;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be max 4 numbers.';
}
}
And to use it:
use App\Rules\MaxNumbers;
$request->validate([
'field_name' => ['required', new MaxNumbers],
]);
You could use the following regex rule:
$this->validate($request, [
'field_name' => 'regex:/^[0-9]+(,[0-9]+){0,3}$/'
]);

Laravel validation using class

I am trying to use Laravel validation : as described here
I am not going to place entire rule class, as it is straight from artisan make:rule.
PROBLEM:
When I try to test 'false' here:
function passes($attribute, $value)
{
return false; //testing 'false' logs me out
}
This is how I use it in controller:
$this->validate($request, [
'image_64' => ['required', new \App\Rules\Base64Rule]
]);
It is like redirect isn't going to form page, but index page - which in my case logs user out (among other things).
Is there any protected var to mark proper redirect route, when method 'passes' returns false?
Anyone came across something like this?
EDIT
Sam,
As I mentioned, rule class is pristine - freshly generated:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Base64Rule 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 false;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The validation error message.';
}
}
If I run on top of my controller anything like:
use App\Rules\Base64Rule;
$rule = new Base64Rule;
dd($rule->passes('image_64', 'udfshjbfisuusoshgosghosh'));
I get whatever I have in rule's method passes().
If I use in rule's method passes() return true; it works right.
If I use in rule's method passes() dd('some'), I get 'some' in that controller test.
When test is 'false' and regular validation code is used:
use App\Rules\Base64Rule;
$this->validate($request, [
'image_64' => ['required', new Base64Rule]
]);
... I get redirected to index page.
I have to follow request/response and see, where Laravel fails and why ... I guess. And is it my code, or a bug.

How can I re-utilise existing validation methods in my custom validation method in Laravel?

Let's say we have the following custom validator:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Validator::extend('email_and_mx_record', function ($attribute, $value, $parameters, $validator) {
//...
});
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
As implied by the validation name, I want to create MX record validation of an email address. First thing is first though, checking the email address format is valid. Now I know that this is simple enough if I simply copy the existing validation logic from the Validator class itself that uses a well known function:
<?php
namespace Illuminate\Validation;
class Validator implements ValidatorContract
{
/**
* Validate that an attribute is a valid e-mail address.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
protected function validateEmail($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
}
But in an ideal world, I would want to stick to the DRY principle.
I am wondering if there is a way to call this method within my custom validator or not? E.g. (doesn't work): return $validator->validateEmail($attribute, $value) ? (do my validation) : false;.
The only solution to this question would be a way not to repeat myself, and piggy-back on the Laravel email validator. For now, I will just copy the existing logic.
If it is possible to do this, it would pave the way for me to enhance other validation methods, so it isn't just an issue of being pedantic.
Instead of calling Laravel email validation function inside your custom validation, I'm wondering why can't you use the email rule as a rule only. There is no need of overriding.
For example :
$this->validate($request, [
'email' => 'bail|email|email_and_mx_record',
...
]);
bail documentation :
Sometimes you may wish to stop running validation rules on an
attribute after the first validation failure. To do so, assign the
bail rule to the attribute:

Laravel authentication error message

I'm using custom authentication. Added user status(enable/disable) check in retrieveByCredentials function of my custom provider. Now how can I differentiate the error, whether its coming because user enter wrong credentials or because user is disabled?
So far I looked at following function sendFailedLoginResponse, but there is no way to differentiate.
Any suggestions how can I achieve this?
I've approached this in the following way:
/*
LoginController.php
*/
/**
* Override default login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
/**
* Override default validation of the user login request.
*
* #param \Illuminate\Http\Request $request
*
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => [
'required',
'min:4',
'max:30',
'regex:/^[\S]*$/',
Rule::exists('users')->where(function ($query)
{
$query->where('active', 1);
})
],
'password' => 'required|min:6|max:100'
]);
}
Substituting out whatever the name and expected value of your field is for "active" will enable you to validate depending on whether or not users are active/enabled. You mentioned you've already done this but in this case the validation error will also be the validation message for the "exists" rule. In my application I don't actually need to care why a user failed login but checking the validation message may, I suppose, be enough in your case?

Resources