[BC] New Version

This version simplifies the api a lot, eliminating unnecesary complexity and reducing the library to a few classes only.
This commit is contained in:
2020-11-20 11:51:33 +00:00
parent 0ad94c4944
commit b4f4fe25b9
32 changed files with 847 additions and 1061 deletions

236
README.md
View File

@@ -1,13 +1,9 @@
Rut Chileno
===========
Esta librería implementa una clase Rut como un *value object* inmutable, incluyendo
una api de validación flexible y extendible.
Esta librería implementa una clase Rut como un sencillo *value object* inmutable.
Además, posee un validador para `symfony/validator`, un *form type* para `symfony/form`
y un *type* para `doctrine/dbal`.
Sólo es compatible con PHP 7.1 o superior.
Además, posee dos *types* para `doctrine/dbal`.
## Instalación
@@ -18,195 +14,101 @@ composer require mnavarrocarter/chilean-rut
```
## Uso
Simplemente instancia una nueva clase con un rut en cualquier formato:
### Parseando un Rut
La clase Rut es capaz de parsear cualquier tipo de rut sin importar el formato usando
el método `Rut::parse()`. Confiadamente puedes poner el valor directamente de un
formulario web y `parse` se encargara de sanitizar el string y ver si el RUT es valido.
```php
<?php
use MNC\ChileanRut\Rut;
$rut = Rut::parse('23.546.565-4');
```
### Validando el Rut
> TLDR: Un objeto `Rut` siempre será valido.
Si tu RUT no es valido, el método `parse` lanzara una excepción de tipo
`MNC\ChileanRut\InvalidRut`. Esto es para seguir buenos principios de *objects
calisthenics*: un objeto de valor siempre se crea en un estado valido, y se mantiene
valido a través de todo su ciclo de vida. No se permiten mutaciones que dejen el
objeto en un estado invalido.
Por esta razón el objecto `$rut` es completamente inmutable. Esto quiere decir
que una vez creado no puedes cambiar su estado interno: solo puedes leer información.
Estos son los unicos métodos que puedes usar:
```php
<?php
use MNC\ChileanRut\Rut;
$rut = new Rut('23.546.565-4');
$rut = Rut::parse('23.546.565-4');
// Si prefieres, puedes usar el factory method
$rut = Rut::fromString('23546565-4');
$rut->getNumber(); // (int) 23546565
$rut->getVerifier(); // (string) 4
```
Por defecto, la clase Rut se valida usando el `Module11RutValidator` si no se pasa
un validador personalizado al momento de instanciación. Esto es para asegurar la
integridad del objeto.
### Formateando el Rut
Si quieres, por alguna extraña razón, deshacerte de esa validación, puedes crear
un `AlwaysValidRutValidator` implementando la interfaz `RutValidator`. El método
validate estaría en blanco, lo que haría pasar la validación sin problema.
```php
<?php
use MNC\ChileanRut\Rut;
use MNC\ChileanRut\Validator\RutValidator;
class AlwaysValidRutValidator implements RutValidator
{
public function validate(Rut $rut) : void
{
// Vacío a propósito
}
}
// Asi, la validación pasa sin problema.
$rut = new Rut('23.546.565-4', new AlwaysValidRutValidator());
```
### Validación Personalizada de Rut
El `Module11RutValidator` no es más que la implementación del validador clásico de Rut,
el algoritmo de módulo 11. Esto verifica que un Rut es algoritmicamente correcto, pero
no valida que es real.
Por ello, proveemos la interfaz `RutValidator`. Con ella, puedes crear tus propias
reglas de validación, como llamar a un web service o consultar una base de datos
para verificar si un Rut es real o no. Te recomiendo mirar la interfaz para
implementarla correctamente.
De todas formas, aquí hay un ejemplo que va a buscar un rut a un web service.
```php
<?php
use MNC\ChileanRut\Validator\RutValidator;
use MNC\ChileanRut\Rut;
use MNC\ChileanRut\Exception\InvalidRutException;
use App\Rut\WebServiceRutChecker;
class MyCustomRutValidator implements RutValidator
{
private $rutChecker;
/**
* MyCustomRutValidator constructor.
* @param WebServiceRutChecker $rutChecker
*/
public function __construct(WebServiceRutChecker $rutChecker)
{
$this->rutChecker = $rutChecker;
}
/**
* @param Rut $rut
*/
public function validate(Rut $rut) : void
{
// Por debajo, esta clase ficticia haría una llamada a un web service preguntando
// si el Rut existe.
if ($this->rutChecker->doesRutExist($rut->format())) {
return;
}
throw new InvalidRutException($rut, 'This rut does not exist');
}
}
```
> NOTA: La implementación de cualquier validador DEBE arrojar un InvalidRutException cuando
el Rut no es válido. De lo contrario, el Rut se toma como válido.
### Usando múltiples validadores
Proveemos un `ChainRutValidator` que puedes usar para validar un rut contra múltiples
validadores. Esto permite ejecutar cadenas de validación, como ver primero si un rut es
válido algorítmicamente antes de verificarlo contra un web service.
Usarlo es simple:
```php
<?php
use MNC\ChileanRut\Rut;
use MNC\ChileanRut\Validator\ChainRutValidator;
use MNC\ChileanRut\Validator\SimpleRutValidator;
use App\Rut\DatabaseRutValidator;
$chainValidator = new ChainRutValidator(
new SimpleRutValidator(),
new DatabaseRutValidator()
);
$rut = new Rut('14.245.245-2');
$chainValidator->validate($rut);
```
### Formateando Ruts a String
Una vez creado el objeto Rut, puedes formatearlo a string en el formato que tu quieras.
Esto se hace a través del método format y cómo parámetro acepta el valor
de una de las constantes `FORMAT_` de la clase Rut.
Existen muchas formas distintas de formatear un rut y esta librería soporta muchas
de ellas. El método format devuelve un objeto al cual puedes encadenar llamadas para
formatear el rut y luego castearlo a un string. La interfaz es encadenable para que
puedas combinar las opciones de formato como quieras.
```php
<?php
use MNC\ChileanRut\Rut;
$rut = new Rut('34244223-4');
$rut = Rut::parse('23.546.565-4');
echo $rut->format(Rut::FORMAT_CLEAR); // Va a imprimir 342442234
echo $rut->format(Rut::FORMAT_READABLE); // Va a imprimir 34.244.223-4
echo $rut->format(Rut::FORMAT_HYPHENED); // Va a imprimir 34244223-4
echo $rut->format(Rut::FORMAT_HIDDEN); // Va a imprimir 34.***.***-4
echo $rut->format()->hyphened(); // 23546565-4
echo $rut->format()->dotted()->hyphened(); // 23.546.565-2
echo $rut->format()->dotted()->hyphened()->obfuscated(); // **.***.565-2
echo $rut->format()->obfuscated()->hyphened(); // *****565-2
echo $rut->format()->obfuscated(); // *****5652
```
### Utilidades
Esta librería provee una clase llamada `CorrelativeUtils` que tiene algunas utilidades
interesantes. Posee tres métodos:
```php
<?php
use MNC\ChileanRut\Util\CorrelativeUtils;
// Este método devuelve el digito verificador de un correlativo.
CorrelativeUtils::findVerifierDigit('34525252');
// Este método devuelve una instancia de Rut válida, sólo con el correlativo.
CorrelativeUtils::createValidRutOnlyFromCorrelative('34525252');
// Este método devuelve instancia de Rut autogenerada algoritmicamente válida.
CorrelativeUtils::autoGenerateValidRut();
```
## Integraciones con Liberías de Terceros
## Integraciones con Librerías de Terceros
### Doctrine DBAL
Esta libería provee un custom type para doctrine llamado `RutType`. Puedes registrarla
en el Dbal para usarla en tus mappings de doctrine y automáticamente mappear tu
el valor de tu db a un objeto rut.
Esta librería provee dos [*Custom Types*](https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/cookbook/custom-mapping-types.html)
para Doctrine, con el objetivo de que puedas mapear tus objetos `Rut` fácilmente
a una base de datos relacional.
### Symfony Validator
Además, esta libería cuenta con un validador para Symfony Validator, que te
permite beneficiarte de las anotaciones del componente de validación de Symfony.
Como dependencia opcional necesita una instancia de `RutValidator`. Si ninguna es proveída,
se utiliza el `SimpleRutValidator`. Solo puedes usar el validador contra una instancia de `Rut`.
El `MNC\ChileanRut\Doctrine\RutType` mapeara tu RUT a una columna VARCHAR.
El string se guarda con puntos y guion. Ex: `16.894.365-2`. Es una forma no tan
eficiente de guardar los RUTS (en términos de espacio), pero ayuda mucho cuando
se visualiza o exporta la base de datos a otras fuentes.
### Symfony Form Type
Por último, esta libería cuenta con un Symfony Form Type que puedes añadir en tus
formularios HTML, para que puedas autoinstanciar la clase y poner lógica de
validación en ella sin problema, y añadirla a tus otros tipos.
El `MNC\ChileanRut\Doctrine\NumericRutType` mapeara tu RUT a una columna INTEGER.
El numero se guarda sin digito verificador y es recalculado cuando la columna
es transformada a un valor PHP. Esta forma de guardar ruts es muy eficiente (en
términos de espacio), pero cuesta comparar y leer los números si visualizas o
exportas los registros en la base de datos.
Por supuesto, puedes elegir el `Type` que más se ajuste a tus necesidades.
## FAQ
### ¿Cómo nació y por qué esta librería?
Esta libería nace de la necesidad de estandarizar una clase Rut común para todos mis proyectos
PHP.
Si bien es cierto, hay muchas liberías con implementaciones de Rut chilenos en PHP,
Esta librería nace de la necesidad de estandarizar una clase Rut común para todos
mis proyectos PHP.
Si bien es cierto, hay muchas librerías con implementaciones de Rut chilenos en PHP,
muchas de ellas tienen notorias deficiencias:
1. No están testeadas unitariamente,
2. No separan bien responsabilidades, como la lógica de validación con la de instanciación.
3. No proveen validación extensible por medio de interfaces, limitando la validación
solo a ser algorítmica.
4. Están acopladas a un framework
5. No proveen herramientas ni integraciones con librerías de terceros.
### ¿Por qué PHP 7.1?
El fin del soporte de PHP 5.6 será a fines de 2018. PHP 7.1 es una de las últimas
versiones estables, y me beneficio mucho de su sistema de tipado estricto en esta libería.
2. No tienen un buen diseño y sus apis tienen efectos secundarios.
3. Están acopladas a un framework (Laravel Rut y otras hierbas)
4. No proveen herramientas ni integraciones con librerías de terceros.
### ¿Por qué PHP 7.4?
PHP 7.3 ya no tiene mucho tiempo de soporte y 8.0 esta ad portas de ser lanzado. Hay que
empujar el ecosistema hacia adelante.