Skip to content

Instantly share code, notes, and snippets.

@rafael-neri
Last active March 6, 2025 11:02
Show Gist options
  • Save rafael-neri/ab3e58803a08cb4def059fce4e3c0e40 to your computer and use it in GitHub Desktop.
Save rafael-neri/ab3e58803a08cb4def059fce4e3c0e40 to your computer and use it in GitHub Desktop.
Validar CPF em PHP (Completo)
<?php
function validaCPF($cpf) {
// Extrai somente os números
$cpf = preg_replace( '/[^0-9]/is', '', $cpf );
// Verifica se foi informado todos os digitos corretamente
if (strlen($cpf) != 11) {
return false;
}
// Verifica se foi informada uma sequência de digitos repetidos. Ex: 111.111.111-11
if (preg_match('/(\d)\1{10}/', $cpf)) {
return false;
}
// Faz o calculo para validar o CPF
for ($t = 9; $t < 11; $t++) {
for ($d = 0, $c = 0; $c < $t; $c++) {
$d += $cpf[$c] * (($t + 1) - $c);
}
$d = ((10 * $d) % 11) % 10;
if ($cpf[$c] != $d) {
return false;
}
}
return true;
}
@rafael-neri
Copy link
Author

@gfucci
Copy link

gfucci commented Feb 11, 2025

@hiltonbruce se a função der um strlen diferente de 11, ele não vai retornar imediatamente a closure $fail, a função vai tentar verificar as outras regras, se o o usuário colocar uma string menor de 9 ele vai jogar um exception de offset quando o php tentar executar o "for". Aqui está o bug corrigido.

/**
     * Run the validation rule.
     *
     * Extrai somente os números
     * Verifica se foi informado todos os digitos corretamente
     * Verifica se foi informada uma sequência de digitos repetidos. Ex: 111.111.111-11
     * Faz o calculo para validar o CPF
     * 
     * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $cpf = apenasNumeros($value);

        if (strlen($cpf) !== 11) {
            $fail('O :attribute deve ter exatamente 11 números.');
        } elseif (preg_match('/(\d)\1{10}/', $cpf)) {
            $fail('O :attribute não deve ser uma sequência de números iguais.');
        } else {
            for ($t = 9; $t < 11; $t++) {
                for ($d = 0, $c = 0; $c < $t; $c++) {
                    $d += $cpf[$c] * (($t + 1) - $c);
                }

                $d = ((10 * $d) % 11) % 10;

                if ($cpf[$c] != $d) {
                    $fail('O :attribute não é um número válido.');
                }
            }
        }
    }

para limpar um pouco mais o código eu coloquei a lógica de regex para limpar os caracteres do cpf em um helper "apenasNumeros", mas a lógica é a mesma ainda.

@FlavioSuarez
Copy link

Obrigado, @rafael-neri !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment