13

I have default validation rule in controller Laravel:

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'phone' => 'required|numeric',
    'code' => 'required|string|min:3|max:4',
    'timezone' => 'required|numeric',
    'country' => 'required|integer',
    'agreement' => 'accepted'
]);

I tried this, but dont know how to transfer some parameters inside function:

public function boot(){
    Validator::extend('phone_unique', function($attribute, $value, $parameters) {
        return substr($value, 0, 3) == '+44';
    });
}

How can I extent this validation by my own rule? For example I need to validate concatination of inputs:

$phone = $request->code.' '.$request->phone;

After check if $phone are exists in database

I want to use this method:

$validator->sometimes('phone', 'required|alpha_dash|max:25', function($input) {
    if ((Auth::user()->phone == $input->phone)) {
        return false;
    } else {
        $t = User::where("phone", $input->phone)->get();
        return ($t->count() > 0) ? false : false; 
    }
});

It does not work under all conditions (True, False) inside.

I added new validation nickname_unique:

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'code' => 'required|string|min:3|max:4',
    'phone' => 'required|phone_unique',
    'timezone' => 'required|numeric',
    'country' => 'required|integer',
    'nickname' => 'required|alpha_dash|max:25',
    'agreement' => 'accepted'
], [
    'phone_unique' => 'Phone already exists!',
    'nickname_unique' => 'Nickname is busy!',
]);

It does not work, even not call validation rule below previos:

Validator::extend('nickname_unique', function ($attribute, $value, $parameters, $validator) {
    dd("Here");
});
4
  • Can you explain a bit, which type of validation you need? Commented Dec 22, 2016 at 13:38
  • I have two incoming parameters: code and phone. I need validate both in one validation function and do request to DB to compare code, phone with existing field in db Commented Dec 22, 2016 at 13:43
  • I've posted the answer, please have a look! Commented Dec 22, 2016 at 14:17
  • doc on Custom Validation Rules using Rule Objects. Commented Nov 4, 2024 at 23:29

4 Answers 4

12

You can define your custom validator inside AppServiceProvider like this:

<?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('phone_unique', function ($attribute, $value, $parameters, $validator) {
          $inputs = $validator->getData();
          $code = $inputs['code'];
          $phone = $inputs['phone'];
          $concatenated_number = $code . ' ' . $phone;
          $except_id = (!empty($parameters)) ? head($parameters) : null;

          $query = User::where('phone', $concatenated_number);
          if(!empty($except_id)) {
            $query->where('id', '<>', $except);
          }

          return $query->exists();
      });

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

You can get all the inputs passed to the validator, by accessing $validator property - getData()

You can just add an extra parameter to your rules array after your custom validation rule (just after the colon) like this:

'phone' => 'required|phone_unique:1',

Pass the id to be ignored while checking entries into the db

The custom validator Closure receives four arguments: the name of the $attribute being validated, the $value of the attribute, an array of $parameters passed to the rule, and the Validator instance.

Now you can call the validator like this:

$validator = Validator::make($request->all(), [
      'email' => 'required|email',
      'code' => 'required|string|min:3|max:4',
      'phone' => 'required|phone_unique:1',
      'timezone' => 'required|numeric',
      'country' => 'required|integer',
      'agreement' => 'accepted'
  ], [
    'phone_unique' => 'Phone already exists!', // <---- pass a message for your custom validator
  ]);

See more about Custom Validation Rules.

Sign up to request clarification or add additional context in comments.

11 Comments

Thnaks, but last part of your answer is not clear for me
The last part just explains, how to use the validator, let me format a code a bit for you again!
I tried validation: $validator->sometimes('nickname', 'required|alpha_dash|max:25', function ($input) {} But it works not stable
From where did you get this, I didn't understand, this is not what you've asked, is it so?
When should work phone_unique wrong validation? When function returns false?
|
6

I am writing this answer because I believe bunch of people are looking for some good answer for this topic. So I decided to share my code that I am using for booking site, where I want to check that IS NOT arrival_date > departure_date.

My Laravel version is 5.3.30

public function postSolitudeStepTwo(Request $request)
{
    $rules = [
        'arrival_date' => 'required|date',
        'departure_date' => 'required|departure_date_check',
        'occasional_accompaniment_requested' => 'required|integer',
        'accommodation' => 'required|integer',
        'are_you_visiting_director' => 'required|integer',
    ];

    if ($request->input('are_you_visiting_director') == 1) {
        $rules['time_in_lieu'] = 'required|integer';
    }

    $messages = [
        'departure_date_check' => 'Departure date can\'t be smaller then Arrival date.Please check your dates.'
    ];

    $validation = validator(
        $request->toArray(),
        $rules,
        $messages
    );

    //If validation fail send back the Input with errors
    if($validation->fails()) {
        //withInput keep the users info
        return redirect()->back()->withInput()->withErrors($validation->messages());
    } else {
        MySession::setSessionData('arrival_date', $request);
        MySession::setSessionData('departure_date', $request);
        MySession::setSessionData('occasional_accompaniment_requested', $request);
        MySession::setSessionData('accommodation', $request);
        MySession::setSessionData('are_you_visiting_director', $request);
        MySession::setSessionData('time_in_lieu', $request);
        MySession::setSessionData('comment_solitude_step2_1', $request);

        //return $request->session()->all();
        return redirect("/getSolitudeStepThree");
    }
}

My controller is StepController and there I have declared a method as you can see called postSolitudeStepTwo. I declare the rules and on departure date notice that for the rule we have required|departure_date_check. That will be the name of the method in

app/Providers/AppServiceProvider.php

The code there looks like this:

public function boot()
{
    Validator::extend('departure_date_check', function ($attribute, $value, $parameters, $validator) {
        $inputs = $validator->getData();
        $arrivalDate = $inputs['arrival_date'];
        $departureDate = $inputs['departure_date'];
        $result = true;
        if ($arrivalDate > $departureDate) {
            $result = false;
        }
        return $result;
    });
}

As the Laravel documentation 5.3 Custom validation rules we need to extend the Validator facade, the signature of that method has to be:

Validator::extend(name_of_the_function, function ($attribute, $value, $parameters, $validator) {

And I believe the rest is clear.

Hope it will help somebody.

Cutom Validation error frontend

Comments

2
$messsages = array(
    'email.required'=>'Email is Required',
    'phone.required'=>'Phone number is Required',
);

$rules = array(
    'email' => 'required',
    'phone' => 'required',
);

$validator = Validator::make(Input::all(), $rules,$messsages);

if ($validator->fails()):
    $this->throwValidationException($request, $validator);
endif;

1 Comment

In your case why not to use something like: 'departure_date' => 'required|date|after:arrival_date' ?
1

If you only need to perform a custom validation once in a specific part of your code, using the add method of the validator is a simple way to achieve it.

This will be more useful when you have a validation rule that’s not required across the entire application, but is needed for a one-off scenario.

Here is an example:

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'phone' => 'required|numeric',
    'code' => 'required|string|min:3|max:4',
    'timezone' => 'required|numeric',
    'country' => 'required|integer',
    'agreement' => 'accepted'
]);


$validator->after(function ($validator) {
    if (!preg_match('/^[0-9]{10}+$/', $input->phone)) {
        $validator->errors()->add(
            'phone_number', 'The phone number must be a valid number.'
        );
    }
});

if ($validator->fails()) {
   return redirect()->back()-> withErrors($validator)->withInput();
}

Reference: https://laravel.com/docs/11.x/validation#performing-additional-validation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.