Laravel 11 validation rule for one item which can be email or phone number?

Updated: Feb 19, 2025

Laravel 11 validation rule for one item which can be email or phone number?

To create a Laravel validation rule for an input field that can accept either an email address or a phone number, you can create a custom validation rule. Here's how you can do it:

  1. Create a new validation rule file in the app/Rules directory. Let's call it EmailOrPhone.php.
namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\Rule;

class EmailOrPhone implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  array  $parameters
     * @return bool
     */
    public function passes($attribute, $value, $parameters)
    {
        return $this->isEmail($value) || $this->isPhoneNumber($value);
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be a valid email address or phone number.';
    }

    /**
     * Determine if the given value is a valid email address.
     *
     * @param  string  $value
     * @return bool
     */
    protected function isEmail($value)
    {
        return filter_var($value, FILTER_VALIDATE_EMAIL);
    }

    /**
     * Determine if the given value is a valid phone number.
     *
     * @param  string  $value
     * @return bool
     */
    protected function isPhoneNumber($value)
    {
        // You can use a library like 'prettus/laravel-validation' or 'mattstauffer/laravel-phone' for more complex phone number validation
        // or use a regular expression for simple validation
        $pattern = '/^(\+\d{1,2}\s)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/';

        return preg_match($pattern, $value);
    }
}
  1. Register the new validation rule with Laravel. Open the app/Providers/AppServiceProvider.php file and add the following code to the boot() method:
use App\Rules\EmailOrPhone;

public function boot()
{
    //
    Validator::resolver(function ($translator, $data, $rules, $messages) {
        return new EmailOrPhone($rules, $messages);
    });
}
  1. Now you can use the new validation rule in your form request or controller validation. For example, in a form request:
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest 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 [
            'contact' => ['required', new EmailOrPhone],
        ];
    }
}

Or in a controller validation:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'contact' => ['required', Rule::emailOrPhone],
        ]);

        // Your code here
    }
}

This custom validation rule will check if the given value is a valid email address or phone number and return an error message if it's not.