dsfsddfsdfsf
dsfsddfsdfsf

Reputation: 155

How to write custom validation rule in controller Laravel?

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");
});

Upvotes: 12

Views: 43211

Answers (4)

UnderIdentityCrisis
UnderIdentityCrisis

Reputation: 56

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

Upvotes: 0

vipinlalrv
vipinlalrv

Reputation: 3065

$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;

Upvotes: 2

Matija
Matija

Reputation: 17902

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

Upvotes: 5

Saumya Rastogi
Saumya Rastogi

Reputation: 13693

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.

Upvotes: 12

Related Questions