viernes, 29 de mayo de 2009

Validador de Rut (PHP)

Llevo harto tiempo en esto del desarrollo de software, he hecho cosas bastantes simpáticas y complejas pero nunca necesité un validador de RUT.

Me puse manos a la obra y la musa dictó:

= 0; $i--):
$factor = $factor > 7 ? 2 : $factor;
$suma += $elRut{$i}*$factor++;
endfor;
$resto = $suma % 11;
$dv = 11 - $resto;
if($dv == 11){
$dv=0;
}else if($dv == 10){
$dv="k";
}else{
$dv=$dv;
}
if($dv == trim(strtolower($RUT[1]))){
return true;
}else{
return false;
}
}
?>


Lo pueden probar acá

9 comentarios:

  1. Nice. Me gustó la parte que hace que puntos y guión no tengan importancia.

    La parte "dura" donde se hacen los cálculos se supone podría ser optimizada, a riesgo de dejar código feo.

    Yo uso esta horripilantez :D


    function dv($r){$s=1;for($m=0;$r!=0;$r/=10)$s=($s+$r%10*(9-$m++%6))%11;
    return chr($s?$s+47:75);}

    ResponderEliminar
  2. El punto que te gustó, también puede ser resuelto con expresiones regulares, sería algo así:

    preg_replace('[^\-\.]','',$rut);


    Posterior a la publicación le hice una reducción en la parte posterior al cálculo quedando así:

    function validaRut($rut){
    if(strpos($rut,"-")==false){
    $RUT[0] = substr($rut, 0, -1);
    $RUT[1] = substr($rut, -1);
    }else{
    $RUT = explode("-", trim($rut));
    }
    $elRut = str_replace(".", "", trim($RUT[0]));
    $factor = 2;
    for($i = strlen($elRut)-1; $i >= 0; $i--):
    $factor = $factor > 7 ? 2 : $factor;
    $suma += $elRut{$i}*$factor++;
    endfor;
    $dv = 11 - ($suma % 11);
    if($dv == 11){
    $dv=0;
    }else if($dv == 10){
    $dv="k";
    }
    if($dv == trim(strtolower($RUT[1]))){
    return true;
    }else{
    return false;
    }
    }

    ResponderEliminar
  3. GRANDE COMPADRE! Esta bueno tu codigo, me sirvio!..

    Felipe.

    ResponderEliminar
  4. Muy muy bueno, se agradece con escándalo!

    ResponderEliminar
  5. Anónimo12:15 a.m.

    Tengo una duda si uno pone el rut con una letra entremedio no da error? por ke seria eso
    esta validando mal o no?

    ResponderEliminar
  6. Con lo que dices veo 2 errores en mi función:

    La primera es que en el ciclo for. Al multiplicar un string por un entero el resultado es 0, el que se va acumulando en $suma. Luego al momento de evaluar el módulo 11, siempre devolverá 11. Entonces al pasar por primer if de evaluación de la variable $dv devolverá 0. Luego al comparar esto con trim(strtolower($RUT[1])) devolverá true porque, y este es el segundo error, es una evaluación de similitud y no de identidad. 0 es igual a trim(strtolower($RUT[1])) porque al fin y al cabo ambos son "algo". Si la evaluación hubiese sido de identidad (===), más estricta, el resultado sería false.

    En resumen, donde dice:

    if($dv == trim(strtolower($RUT[1])))

    cámbialo por:

    if($dv === trim(strtolower($RUT[1]))).

    ResponderEliminar
  7. Holas,
    Llegué en busca de rápida solución al deprecado ereg_replace('\.|,|-','',$rut);

    coments:
    agregué inicializar $suma=0;
    Patina la redacción de "El rut 1226451a-4 no es incorrecto"

    con eso ya andó bien, gracias!

    ResponderEliminar
  8. update: con $dv === trim(strtolower($RUT[1]) siempre entrega false.

    ResponderEliminar
  9. Anónimo7:00 p.m.

    funciona el codigo, pero tambien deberia indicar rut invalido cuando se pone solo letras

    ResponderEliminar