validazione form con opzioni da doctrine

21 views
Skip to first unread message

Vercinstex

unread,
Apr 5, 2017, 10:17:37 AM4/5/17
to symfony-it
Ciao a tutti
ho una domanda banale e magari stupida.

stavo creado un validatore per vari form, personalizzato e sono bloccato. Non so bene come procedere in quanto anche la guida ufficiale non mi è molto chiara.
In ogni caso.

Nel mio form ho un campo che rappresenta un entità base, è disabilitato perchè mi serve come riferimento.
Questa entità base ha due parametri che vorrei usare per la validazione.

Ok, ora nel mio form inserisco varie informazioni, un paio di queste dovranno essere conformi ai due parametri di base dell'entità che vorrei passare.

Come posso fare per associare il validator ad un entità che scelgo io arbitrariamente (nell'url è inserito l'id dell'entità di cui ho bisogno) ??
Chiedo questo perchè mi sembra di aver capito che i validator debbano avere la forma di (value, constraint) e non è possibile aggiungere altri parametri o sbaglio??

Avete qualche suggerimento da darmi per provare??
Grazie mille
S.


Vercinstex

unread,
Apr 5, 2017, 11:15:07 AM4/5/17
to symfony-it
Non so se sia la strada giusta o meno ma mi sono portato avanti ed ho fatto così:

Nel file servizio in cui dichiaro il validator gli passo come argomenti:

arguments: ["@doctrine.orm.entity_manager", "@request_stack"]

in maniera tale che mi dia l'accesso a doctrine ed alla request dal quale estrarre il parametro ID che mi permettere poi di recuperare la mia entità di base.
Che dite??
Sto procedendo nel verso giusto o la procedura può essere migliorata??

Grazie mille
S.

Massimiliano Arione

unread,
Apr 7, 2017, 11:21:22 AM4/7/17
to symfony-it
Devi cambiare punto di vista: la validazione non è sul form (OK ci sono casi particolari, lasciamoli da parte), è sull'entity.
È l'entity che viene validata, il form è solo un punto di passaggio per inserire valori nell'entity (anche qui non è da prendere in senso assoluto)
Se quell'altra entity che stai usando nel form è in relazione con la tua entity principale, usala per una validazione callback. Se non è in relazione, probabilmente stai sbagliando qualcosa nel tuo approccio

ciao
M.


Il giorno mercoledì 5 aprile 2017 16:17:37 UTC+2, Vercinstex ha scritto:

Vercinstex

unread,
Apr 10, 2017, 3:45:24 AM4/10/17
to symfony-it
Ciao
Intanto grazie per la risposta, sono stato un po' incasinato ma ho già iniziato a darci un occhio veloce alle callback per la validazione.

Guarda questo screenshot di esempio:


Come vedi l'entità macchina è quella che comanda, al quale poi associo eventuali lotti di produzione.
La mia idea è quella che durante la registrazione dei lotti di produzioni il numero di serie iniziale e finale vengano validati secondo le opzioni "serial_base" e "serial_remove" dell'entità macchina.
Le due tabelle sono collegate tramite l'id della macchina.

Ora mi chiedo, la via più corretta è quella delle callback?? così che possa essere passato l'oggetto macchina giusto??
Sono sulla buona strada??

Attendo riscontro
Grazie mille
Stefano
Auto Generated Inline Image 1

Massimiliano Arione

unread,
Apr 10, 2017, 3:54:51 AM4/10/17
to symfony-it
Esatto.
Come ipotizzavo in precedenza, dentro all'entity Lotto hai $this->machine.
A questo punto nel callback di validazione di Lotto puoi usare i vari $this->machine->getSerialStart() ecc. per costruire la tua validazione

ciao
M.

Vercinstex

unread,
Apr 10, 2017, 8:00:20 AM4/10/17
to symfony-it
Grazie mille
Appena ho un attimo ci guardo per implementarlo e ti aggiorno :)
Grazie ancora e buona giornata

Vercinstex

unread,
Apr 11, 2017, 10:50:03 AM4/11/17
to symfony-it
Ciao
Ho iniziato a darci un occhio.
Onestamente la guida sul sito di symfony mi sembra un po' poco chiara, ma comunque provando a mettere insieme qualche pezzo mi sono portato avanti.
Ovvero...

Leggevo che è possibile usare un validatore per la callback esterno alla classe (qui ti chiederò il primo consiglio) e quindi ho creato in AppBundle\Validator\Classe.php come validatore esterno.
Al momento ho messo giusto un codice base purchè mi ritorni errore.

<?php

namespace AppBundle\Validator;

use Symfony\Component\Validator\Context\ExecutionContextInterface;

class SerialValidator
{
   
public static function validate($object, ExecutionContextInterface $context, $payload)
   
{
       
dump($object);
       
dump($context->getObject()->getMachine());
       
         
if (true) {
            $context
->buildViolation('Errore Form')
               
->addViolation();
           
       
}
       
// ...
   
}
}

Ho pensato a fare questa cosa perchè la stessa strategia di validazione mi servirà poi anche per altre occasioni, e quindi non volevo duplicare codice continuamente.
Poi nella classe entity in cui mi serve la validazione ho messo la seguente istruzione alle relative proprietà:
@Assert\Callback({"AppBundle\Validator\SerialValidator", "validate"})

Mi sembra che il tutto funzioni, ora la mia preoccupazione sarà fare in modo da rendere il tutto usabili nella maggior vastità di situazioni possiibili.

Hai qualche consiglio da darmi??
Suggerimenti??

Attendo tuo riscontro
Grazie mille
Saluti
S.

Massimiliano Arione

unread,
Apr 11, 2017, 10:57:06 AM4/11/17
to symfony-it
Il mio suggerimento è di restare sullo specifico ed eventualmente generalilzzare successivamente.
Comunque generalizzare il meno possibile, perché generalizzando ti perdi sicuramente qualcosa.
Ora per esempio hai altre entity che hanno la stessa relazione con Machine? Nel caso, potresti usare un'entity astratta che contiene la relazione e il validatore, poi estendere quella.
Se invece vuoi riciclare il validatore per relazioni diverse, lascia perdere, è troppo generica come soluzione

ciao
M.

Vercinstex

unread,
Apr 12, 2017, 4:06:54 AM4/12/17
to symfony-it
CIao Massimiliano
Grazie per la risposta.
In realtà si avrò altre entity dove ci sarà una relazione simile e dove la validazione sul numero di serie di machine sarà sempre uguale, per questo avevo pensato a non duplicare il codice.
Per esempio nella mi app, avrò come hai visto la possibilità di associare ad una specifica Machine uno o più eventuali lotti di produzione. E qui la mia prima necessità di verifica sui numeri di serie.
Ma allo stesso tempo, la mia app mi permetterà anche di salvare nel DB eventuali difetti relativi ad una specifica macchina. E quindi anche qui quando riporto il difetto che sarà accompagnato da un numero di serie della macchina dovrò validarlo.
Se serve qualche dettaglio in più per farti capire, dimmi pure.
Alla fine sono qui per imparare e voglio farlo per bene, sopratutto perchè noto che a volte alcuni concetti mi mancano, nello specifico il tuo suggerimento della classe astratta con la relazione non mi è ben chiaro se può fare al caso mio e quali vantaggi potrebbe portarmi.

Attendo tuoi suggerimenti e se hai qualche link che psosa aiutarmi a studiare meglio qualche concetto te ne sarei grato.
Grazie mille
Stefano

Massimiliano Arione

unread,
Apr 12, 2017, 4:19:26 AM4/12/17
to symfony-it
Per la soluzione della classe astratta con campi (e metodi) comuni ti rimando alla documentazione ufficiale http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html

ciao
M.

Vercinstex

unread,
Apr 18, 2017, 10:31:21 AM4/18/17
to symfony-it
Ciao Massimiliano
Ho finalmente dato un occhio alla documentazione, e se non ho inteso male quello che devo usare è una classe "mappedsuperclass" per tt quelle tabelle che hanno relazione con machine, come per esempio lotto che hai visto anche tu.
Per esempio:

/**
 * @MappedSuperclass
 */
class Serial
{
   
/**
     * @var string
     *
     * @Assert\Callback({"AppBundle\Validator\SerialValidator", "validate"})
     */

   
private $serial;
}

Nella tabella lotto che estende Serial per esempio:
/**
 * Lotto
 *
 * @ORM\Table(name="lotto")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\LottoRepository")
 *
@Entity
 * @AttributeOverrides({
 *      @AttributeOverride(name="serial",
 *          column=@Column(
 *              name     = "serial_start",
 *              type     = "string",
 *              length   = 45,
 *              unique   = true,
 *          )
 *      ),
 * })
*/
class Lotto extends Serial {

/* bla bla bla */
/* bla bla bla */
}

E poi dentro la classe io posso agire come se fosse un attributo di lotto normale e quindi mi permette di fare le funzioni getserialstart etc etc giusto??
La validazione sarebbe da mettere nella mappedsuperclass (Serial) oppure nella classe normale (Lotto) e nel caso sempre con un validatore dedicato??


Però ho un dubbio, che mi è venuto leggendo la documentazione.
Ovvero, io con serial non ho una relazione diretta tra machine e lotto attraverso il serial. (o non centra nulla??)
La mia relazione è con id (oggetto machine) semplicemente per capire a quale tipologia di macchina appartiene un certo lotto.
Infatti ricavando l'oggetto Lotto symfony già mi da l'oggetto Machine con tutti i suoi attributi.

Provo ulteriormente a spiegare il mio flow che vale per lotto ma anche per altre situazioni che avrò:
Ho una pagina dedicata dove con una tendina scelgo il modello di macchina ed inserisco serial_start (numero di serie dal quale parte il lotto) e serial_end numero di serie col quale finisce il lotto più la data di produzione del lotto stesso.
Quando io invio il suddetto form, la mia intenzione era avendo già l'oggetto Machine, lo passo al validatore per i campi serial. Il validatore ricevendo l'oggetto machine carica i campi che userò per definire le regole di validazione, $serial_start;  $serial_base; $serial_remove.
Dentro il validatore eseguo tutta la mia logica di controllo ed in caso di problemi creo la violazione.

Ora ho il che tu possa aver inteso una relazione diretta con SERIAL e quindi usare la mappedsuperclass oppure mi sono per io per strada e non capisco su quale linea procedere. Nel caso ti chiedo scusa.

Ho paura che mi sto perdendo in un bicchier d'acqua.

Attendo se puoi qualche tuo chiarimento in merito.
Grazie mille come sempre
Stefano

Vercinstex

unread,
Apr 19, 2017, 6:25:56 AM4/19/17
to symfony-it
Ciao Massimiliano
Ho fatto un primo test con la superclass, e ne ho capito le potenzialità per evitare di ripetere i campi nel caso le entità sfruttino gli stessi campi, il problema è che io non posso usare la superclass per poi fai l'override di molteplici campi partendo da uno singolo della superclass, quindi la mia domanda è, nel mio caso perchè dovrei usarla rispetto a validare i campi che necessito singolarmente??
Esempio:
lotto ha 2 volte il numero di serie, uno all'inizio del lotto ed uno alla fine.
Ma per esempio se devo segnalare una singolo macchinario, quindi un solo numero di serie.
Per ciò non posso sfruttare la stessa superclass.

Scusa se magari le mie domande sembrano stupide, ma cerco sempre di non dare mai nulla per scontato al fine di capire nel miglior modo possibile.
Qualche consiglio??
Grazie mille
Stefano

Massimiliano Arione

unread,
Apr 28, 2017, 4:52:00 AM4/28/17
to symfony-it
La superclass dovrà per forza di cose contenere solo i campi comuni e i metodi comuni (tra cui quello di validazione)
Ho abbastanza chiaro il tuo dominio e ho capito che non hai la relazione diretta con serial, ma avendo quella con machine puoi fare tranquillamente $this->machine->getSerial()

ciao
M.
Reply all
Reply to author
Forward
0 new messages