2012-11-07 19 views
6

Ho un modulo per la registrazione dell'utente e nel modulo è presente solo il campo del nome utente. E nella mia forma, desidero consentire all'utente di inserire solo il nome utente. Nicename sarebbe uguale al nome utente registrato.Validazione dei campi non presenti nel modulo ma nell'entità

Questo modulo è legarsi a un'entità utente, vale a dire, nella mia classe Tipo modulo:

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'Some\Bundle\Entity\User', 
    )); 
} 

entità User, che ha un vincolo NotBlank set sia per nome utente e la nicename.

namespace Some\Bundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Constraints; 

//... 

class User 
{ 
    //... 

    /** 
    * @var string $username 
    * 
    * @ORM\Column(name="user_login", type="string", length=60, unique=true) 
    * @Constraints\NotBlank() 
    */ 
    private $username; 

    /** 
    * @var string $nicename 
    * 
    * @ORM\Column(name="user_nicename", type="string", length=64) 
    * @Constraints\NotBlank() 
    */ 
    private $nicename; 

    //... 

Tuttavia, se costruisco un modulo con solo il nome utente, ma non nicename, sulla convalida cioè $form->isValid() non riesce a convalidare.

Per bypassare questo, vengo con la seguente:

namespace Some\Bundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Some\Bundle\Form\Type\RegisterType; 
//... 

class UserController extends Controller 
{ 
    //... 
public function registerAction() 
{ 
    //... 
    $request = $this->getRequest(); 
    $form = $this->createForm(new RegisterType()); 

    if ($request->getMethod() == 'POST') { 
     // force set nicename to username. 
     $registerFields = $request->request->get('register'); 
     $registerFields['nicename'] = $registerFields['username']; 
     $request->request->set('register', $registerFields); 

     $form->bind($request); 

     if ($form->isValid()) { 
      $user = $form->getData(); 
      //persist $user, etc... 

E in forma tipo aggiungo questo al mio buildForm metodo:

$builder->add('nicename', 'hidden'); 

Ma trovo questo molto poco elegante, lasciare un po ' carico per il controllore (estrarre dall'oggetto richiesta, inserire dati e reinserirlo nell'oggetto richiesta, ahi!), e l'utente può vedere il campo nascosto se deve ispezionare il codice sorgente dell'HT generato.

Esiste comunque che almeno un controller che utilizza il tipo di modulo non debba eseguire operazioni come sopra, pur mantenendo i vincoli di entità?

Non riesco a modificare lo schema della tabella che esegue il backup dell'entità Utente e vorrei mantenere il vincolo NotBlank.


EDIT: Dopo una lunga controversia, ho deciso di utilizzare i gruppi di convalida e ha funzionato.

class User 
{ 
//... 

/** 
* @var string $username 
* 
* @ORM\Column(name="user_login", type="string", length=60, unique=true) 
* @Constraints\NotBlank(groups={"register", "edit"}) 
*/ 
private $username; 

/** 
* @var string $nicename 
* 
* @ORM\Column(name="user_nicename", type="string", length=64) 
* @Constraints\NotBlank(groups={"edit"}) 
*/ 
private $nicename; 

tipo di modulo:

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'Some\Bundle\Entity\User', 
     'validation_groups' => array('register', 'Default') 
    )); 
} 

Questo 'Default' è necessario o ignora tutti gli altri vincoli ho aggiunto nel metodo tipo di modulo buildForm ... Intendiamoci, la sua maiuscole e minuscole: 'default' non funziona.

Anche se, trovo che non è sufficiente (e scusate non ho messo nella mia domanda iniziale), perché quando io persisto, ho bisogno di fare questo nel mio controller:

$user->setNicename($user->getUsername()); 

Come un bonus, mi muovo questo dal controllore al modulo di livello tipo con l'aggiunta di un Form Event Subscriber

Nel tipo di modulo buildForm metodo:

$builder->addEventSubscriber(new RegisterPostBindListener($builder->getFormFactory())); 

E il RegisterPostBindListen er classe

<?php 
namespace Some\Bundle\Form\EventListener; 

use Symfony\Component\Form\Event\DataEvent; 
use Symfony\Component\Form\FormFactoryInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\Form\FormEvents; 

class RegisterPostBindListener implements EventSubscriberInterface 
{ 

public function __construct(FormFactoryInterface $factory) 
{ 

} 

public static function getSubscribedEvents() 
{ 
    return array(FormEvents::POST_BIND => 'setNames'); 
} 

public function setNames(DataEvent $event) 
{ 
    $data = $event->getData(); 

    $data->setNicename($data->getUsername()); 
} 
} 

risposta

0

Nella tua entità utente si può dire quale campo può essere annullabile:

/** 
*@ORM\Column(type="string", length=100, nullable=TRUE) 
*/ 
protected $someVar; 

In questo modo i controller di vista non hanno bisogno di fare nulla.

Hai dimenticato di menzionare. È inoltre possibile definire una condizione PrePersist che inizializza la variabile nicename:

// you need to first tell your User entity class it has LifeCycleCallBacks: 

/** 
* @ORM\Entity() 
* @ORM\HasLifecycleCallbacks() 
*/ 
class User 
{ 

    ... 

    /** 
    *@ORM\PrePersist 
    */ 
    public function cloneName() 
    { 
     $this->nicename = $this->username; 
    } 
} 
+0

Non riesco a impostare nullable perché quell'entità è basata su una tabella il cui schema non può essere modificato. ... certo che potrei, ma rischierei di persistere sugli errori SQL. – luiges90

+0

Nella funzione __construct() della tua entità, potresti semplicemente fornire all'entità dei valori predefiniti per prevenire l'errore NULL. – Zhang

+0

Vorrei mantenere effettivamente il vincolo NotBlank per l'entità. Ho provato a usare la tua strada, ma funziona solo se non c'è '@Constraints \ NotBlank()' per il campo. – luiges90

0

In questo caso, è necessario utilizzare un'asserzione Callback per creare una regola di convalida personalizzata.

Problemi correlati