2013-02-22 10 views
11

Sto scrivendo la mia classe CAPTCHA e quando il modulo non convalida, non voglio precompilare l'input captcha con la risposta precedente, per ovvi motivi. Voglio solo cancellare l'input prima che sia reso.Come cancellare il valore del campo con i moduli Symfony2

Ho scoperto l'dati l'opzione è solo per il valore predefinito, che viene sovrascritto da ciò che l'utente inserisce. Ho provato il seguente codice:

$form->get('captcha')->setData(null); 

.. Dopo la richiesta è legato con la forma, ma un AlreadyBoundException viene generata. Ho effettivamente riuscito a farlo funzionare con:

if (isset($formView->children['captcha'])) { 
    $formView->children['captcha']->vars['value'] = null; 
} 

Ma che sembra proprio sbagliato, e sicuramente non all'altezza degli standard Symfony. Ho esaminato le altre opzioni che puoi fornire durante la creazione del modulo, ma non riesco a vedere nulla di importante.

Qualcuno ha qualche idea?

A proposito, mi aspetto che Symfony2 venga fornito con una soluzione CAPTCHA, questo è principalmente un esercizio di apprendimento mentre mi abituo al framework.

+0

Come si costruisce il modulo? Direttamente nel tuo controller? Stai usando fullstack o solo il componente del modulo? – Schwierig

+0

Ho l'applicazione Symfony completa. Il modulo ha una propria classe che estende AbstractType, che gestisce l'aggiunta di ciascuno dei campi. – Adam

+0

Puoi pubblicare il codice del tuo tipo? – Schwierig

risposta

5

Penso che si voglia gestire questo campo modulo come Symfony gestisce un campo password: non verrà popolato. Diamo uno sguardo alla PasswordType:

namespace Symfony\Component\Form\Extension\Core\Type; 

class PasswordType extends AbstractType 
{ 
    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     if ($options['always_empty'] || !$form->isSubmitted()) { 
      $view->vars['value'] = ''; 
     } 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'always_empty' => true, 
      'trim' => false, 
     )); 
    } 

    //... 
} 

Quindi, è abbastanza semplice: basta aggiungere $view->vars['value'] = '' nel metodo della vostra FormType (vale a dire CaptchaType) buildView. Ciò significa che i dati del campo non vengono cancellati, ma non verranno passati al modello Twig. Approccio diverso, ma il risultato è lo stesso: il campo della password rimane vuoto dopo la convalida non riuscita.

Se sei veramente pigro, puoi usare il PasswordType, ma dal momento che l'input di quel campo sarà mascherato (*****), ciò renderà ancora più noioso un campo captcha fastidioso.

il tuo tipo di modulo forse simile a questa:

class CaptchaType extends AbstractType 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $view->vars['value'] = ''; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getParent() 
    { 
     return __NAMESPACE__.'\TextType'; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getName() 
    { 
     return $this->getBlockPrefix(); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getBlockPrefix() 
    { 
     return 'captcha'; 
    } 
} 

Edit: appena scoperto che CaptchaBundle ha preso il same approach.

0

È possibile passare un'entità incompleta all'azione richiamata quando il controllo rileva un modulo non valido.

public function updateAction(Request $request, $id) 
{ 
    $entity = $this->EM()->getRepository('Bundle:Entity')->find($id); 
    if (!$entity) { 
     throw $this->createNotFoundException('Unable to find Entity entity.'); 
    } 

    $form = $this->createForm(new RecommendationType() 
     ,$entity 
     ,array(
      'attr'   => array(
       ,'entity'   => $entity 
       ) 
      ) 
     ); 

    $form->bind($request); 
    if ($form->isValid()) { 
     $this->EM()->persist($entity); 
     $this->EM()->flush(); 

     return $this->redirect($this->generateUrl('entity_show' 
      ,array('id' => $id))); 
    } else { 
     $entity->setCapthca(Null); 
    } 

    return $this->render('Bundle:Entity:edit.html.twig' 
     ,array(
      'entity'   => $entity 
      ,'form'    => $form->createView() 
      ) 
     ); 
} 

L'azione creare avrebbero modifiche simili.

+0

Grazie, ma il modulo di contatto non è un'entità. È solo un tipo di modulo con i dettagli inviati via email; non ci sono getter/setter su di esso. – Adam

3

C'è un modo divertente per modificare la richiesta prima di gestirla. Tuttavia guarderei la risposta di Stephan come sembra più pulita.

Qualcosa in questo modo:

public function indexAction(Request $request) 
{ 

    $form = $this->createForm(Form::class); 

    $subData=$request->request->get('form'); 

    $subData['task']=null; 

    $request->request->set('form',$subData); 

    $form->handleRequest($request); 


    if ($form->isValid()) { 

     //do stuff 
    } 


    return $this->render('default/index.html.twig', array(
     'form' => $form->createView() 
    )); 
} 

ottenere presentato dati con la 'forma' nome come un array di valori, modificare detto valore a null, quindi impostare il valore della richiesta con il nuovo e hanno la forma occupatene.

E un semplice modulo

class Form extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('task') 
      ->add('save', SubmitType::class);  

    } 

} 

Non importa ciò che si digita, i dati saranno sempre nullo dopo l'invio del modulo. Ovviamente, è necessario verificare il captcha prima di impostare il valore su null.

Problemi correlati