Skip to content

Instantly share code, notes, and snippets.

@sahibalejandro
Last active June 29, 2021 23:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sahibalejandro/8d77e74463a825f3cbd8 to your computer and use it in GitHub Desktop.
Save sahibalejandro/8d77e74463a825f3cbd8 to your computer and use it in GitHub Desktop.
Laravel's RFC Validator
<?php
/**
* @author Sahib J. Leo <sahib@sahib.io>
* Date: 11/24/15 8:53 AM
*/
namespace App\Validation;
class RfcValidator
{
/**
* Regla de validación para un RFC.
*
* @param string $attribute
* @param string $value
* @param array $parameters
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return boolean
*/
public function validate($attribute, $value, $parameters, $validator)
{
if (!$this->correctLenght($value)) {
return false;
}
if (!preg_match($this->pattern($value), $value, $matches)) {
return false;
}
if (!$this->hasValidDate($matches)) {
return false;
}
return true;
}
/**
* Verifica que el RFC tenga una longitud correcta.
*
* @param string $rfc
* @return bool
*/
private function correctLenght($rfc)
{
$length = mb_strlen($rfc);
// El RFC debe ser de 12 letras para personas morales y 13 para personas
// físicas, cualquier longitud fuera de ese rango resulta en un RFC
// inválido.
return $length >= 12 && $length <= 13;
}
/**
* Devuelve el patrón que debe ser usado por preg_match() para el RFC en
* cuestión.
*
* @see https://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(México)
* @param string $rfc
* @return string
*/
private function pattern($rfc)
{
$length = mb_strlen($rfc);
// El RFC debe comenzar con 3 letras para personas morales, o con 4
// letras para personas físicas.
$lettersLength = ($length == 12) ? 3 : 4;
return '/^[A-ZÑ&]{' . $lettersLength . '}([0-9]{2})([0-1][0-9])([0-3][0-9])[A-Z0-9]{2}[0-9A]$/iu';
}
/**
* Verifica si el RFC tiene una fecha válida a partir de los 'match' del
* resultado de preg_match().
*
* @param array $matches
* @return bool
*/
private function hasValidDate($matches)
{
// Extraemos los datos de la fecha para poder validar su integridad.
$year = (int)$matches[1];
$month = (int)$matches[2];
$day = (int)$matches[3];
// Si el año es menor a 70 se asume que es después del año 2000.
$year < 70 ? $year += 2000 : $year += 1900;
return checkdate($month, $day, $year);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment