Validation Framework | Episodio 3 cover image

Validation Framework | Episodio 3

alberto • August 17, 2022

validation

Nonostante il caldo torrido siamo ancora qua, al terzo appuntamento della serie dedicata alla validazione.

In questa puntata faremo un excursus sulle regole che si occupano di validare le date, strutture dati spesso particolarmente complesse e scomode da gestire perchè non seguono le classiche regole matematiche.

Le regole disponibili sono 7 ma possiamo benissimo raggrupparle in due cluster: - le regole che validano la bontà sintatica di una data - le regole che validano che una data sia inclusa in un determinato intervallo

Validazione sintattica delle date

Per assicurarci che un determinato input utente sia una data valida, Laravel ci mette a disposizione due strumenti: date e date_format.

La differenza è banale: la regola date utilizza la funzione nativa PHP strtotime per verificare la bontà del campo (escludendo eventuali date relative), mentre date_format permette di definire un particolare formato, sfruttando la classe PHP DateTime.

Ma guardiamo due esempi esplicativi:

public function test_date_19830615_is_valid()
{
    $validator = Validator::make([
        'birthday' => '1983-06-15'
    ], [
        'birthday' => 'date'
    ]);

    $this->assertFalse($validator->fails());
}

public function test_date_19830230_is_valid()
{
    $validator = Validator::make([
        'birthday' => '1983-02-30'
    ], [
        'birthday' => 'date'
    ]);

    $this->assertTrue($validator->fails());
}

public function test_date_19830615_in_string_is_valid()
{
    $validator = Validator::make([
        'birthday' => '15 June 1983'
    ], [
        'birthday' => 'date'
    ]);

    $this->assertFalse($validator->fails());
}

public function test_relative_date_is_not_valid()
{
    $validator = Validator::make([
        'birthday' => 'now'
    ], [
        'birthday' => 'date'
    ]);

    $this->assertTrue($validator->fails());
}

public function test_random_string_is_not_valid()
{
    $validator = Validator::make([
        'birthday' => 'randomstring'
    ], [
        'birthday' => 'date'
    ]);

    $this->assertTrue($validator->fails());
}

In questo primo esempio vediamo la regola date in esecuzione. Da notare che la stringa now, anche se accettata da strtotime, viene considerata un insuccesso proprio perchè è una data relativa e potrebbe creare non pochi problemi qualora venisse accettata. Il resto sono casi abbastanza semplici.

public function test_date_format_19830615_is_valid()
{
    $validator = Validator::make([
        'birthday' => '1983-06-15'
    ], [
        'birthday' => 'date_format:Y-m-d'
    ]);

    $this->assertFalse($validator->fails());
}

public function test_date_format_19830230_is_valid()
{
    $validator = Validator::make([
        'birthday' => '1983-02-30'
    ], [
        'birthday' => 'date_format:Y-m-d'
    ]);

    $this->assertTrue($validator->fails());
}

public function test_date_format_15061983_in_string_is_valid()
{
    $validator = Validator::make([
        'birthday' => '15/06/1983'
    ], [
        'birthday' => 'date_format:d/m/Y'
    ]);

    $this->assertFalse($validator->fails());
}

L'utilizzo di date_format è simile, cambia solamente il formato della data in ingresso.

Attenzione ad utilizzare in maniera esclusiva date e date_format. Usarle entrambe nella stessa validazione potrebbe non generare l'effetto sperato.

Validazione semantica delle date

Spesso non ci basta essere sicuri che quella che stiamo ricevendo in input sia davvero una data, ma abbiamo anche bisogno di controllare che sia valida da un punto di vista semantico, ovvero che rappresenti una data che ci va bene. Per esempio una data di nascita non puó essere nel futuro, cosi come un evento a calendario non puó essere creato nel passato.

Laravel ci mette a disposizione altre 5 regole di validazione: - after - after_or_equal - before - before_or_equal - date_equals

Le regole si configurano praticamente allo stesso modo: tutte necessitano un parametro aggiuntivo che rappresenta la data contro la quale fare il confronto. Questa data deve essere espressa in un formato accettato dalla solita strtotime (e in questo caso le date relative sono accettate).

Escludendo date_equals, è anche possibile, come parametro addizionale, passare il nome di un altro campo in input per fare il confronto con esso invece che con una data specifica.

Inoltre è buona norma includere in validazione almeno una tra le due precendenti regole sintattiche (date o date_format).

Ma guardiamo alcuni esempi:


public function test_date_is_before_than_now() { $validator = Validator::make([ 'birthday' => '1983-06-15' ], [ 'birthday' => 'date_format:Y-m-d|before:now' ]); $this->assertFalse($validator->fails()); } public function test_date_is_before_than_other_field() { $validator = Validator::make([ 'birthday' => '15/06/1983', 'first_teeth' => '30/03/1980' ], [ 'birthday' => 'date_format:d/m/Y|before:first_teeth', 'first_teeth' => 'date_format:d/m/Y' ]); $this->assertTrue($validator->fails()); } public function test_date_is_after_than_other_field() { $validator = Validator::make([ 'birthday' => '15/06/1983', 'earth_explosion' => '30/03/2080' ], [ 'birthday' => 'date_format:d/m/Y', 'earth_explosion' => 'date_format:d/m/Y|after:birthday' ]); $this->assertFalse($validator->fails()); } public function test_date_is_equals_to_fixed_date() { $validator = Validator::make([ 'today' => '2000-01-01' ], [ 'today' => 'date_format:Y-m-d|date_equals:2001-01-01' ]); $this->assertTrue($validator->fails()); }

Alla prossima

Gli esempi finali sono abbastanza esplicativi e non mi dilungo nella loro spiegazione. Ho ovviamente aggiornato il gist con i nuovi file completi dei test.

Alla prossima