0
votes

I'm hoping someone can point me in the right direction here. This is my first Symfony project, and I'm stumped on why the form won't validate.

To test the application, I fill out all of the form inputs and click the submit button and it fails to validate every time. No idea why.

Any help will be appreciated!

The view -- modules/content/templates/commentSuccess.php :

<?php echo $form->renderFormTag('/index.php/content/comment') ?>
<table>
    <?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>
    <?php echo $form['email']->renderRow(array('onclick' => 'this.value = "";'), 'Your Email') ?>
    <?php echo $form['subject']->renderRow() ?>
    <?php echo $form['message']->renderRow() ?>
    <tr>
        <td colspan="2">
            <input type="submit" />
        </td>
    </tr>
</table>
</form>

The controller -- modules/content/actions/actions.class.php :

public function executeComment($request)
{
    $this->form = new ContentForm();

    // Deal with the request
    if ($request->isMethod('post'))
    {
        $this->form->bind($request->getParameter("content"));

        if ($this->form->isValid())
        {

            // Do stuff
            //$this->redirect('foo/bar');
            echo "valid";
        }
        else
        {
            echo "invalid";
        }
    }
}

The form -- /lib/form/ContentForm.class.php :

class ContentForm extends sfForm {

    protected static $subjects = array('Subject A', 'Subject B', 'Subject C');

    public function configure()
    {
        $this->widgetSchema->setNameFormat('content[%s]');
        $this->widgetSchema->setIdFormat('my_form_%s');
        $this->setWidgets(array(
            'name' => new sfWidgetFormInputText(),
            'email' => new sfWidgetFormInput(array('default' => '[email protected]')),
            'subject' => new sfWidgetFormChoice(array('choices' => array('Subject A', 'Subject B', 'Subject C'))),
            'message' => new sfWidgetFormTextarea(),
        ));
        $this->setValidators(array(
            'name' => new sfValidatorString(),
            'email' => new sfValidatorEmail(),
            'subject' => new sfValidatorString(),
            'message' => new sfValidatorString(array('min_length' => 4))
        ));
        $this->setDefaults(array(
            'email' => '[email protected]'
        ));
    }

}

Thanks in advance! I'll edit this post as needed during progress.

EDIT I've changed my view code to this:

<?php echo $form->renderFormTag('/frontend_dev.php/content/comment') ?>

<table>
    <?php if ($form->isCSRFProtected()) : ?>
        <?php echo $form['_csrf_token']->render(); ?>
    <?php endif; ?> 

    <?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>
    <?php echo $form['email']->renderRow(array('onclick' => 'this.value = "";'), 'Your Email') ?>
    <?php echo $form['subject']->renderRow() ?>
    <?php echo $form['message']->renderRow() ?>

    <?php if ($form['name']->hasError()): ?>
        <?php echo $form['name']->renderError() ?>
    <?php endif ?>


    <?php echo $form->renderGlobalErrors() ?>

    <tr>
        <td colspan="2">
            <input type="submit" />
        </td>
    </tr>
</table>
</form>

This gives a required error on all fields, and gives " csrf token: Required. " too.

My controller has been updated to include $this->form->getCSRFToken(); :

public function executeComment($request)
    {
        $this->form = new ContentForm();
        //$form->addCSRFProtection('flkd445rvvrGV34G');
        $this->form->getWidgetSchema()->setNameFormat('contact[%s]');

        $this->form->getCSRFToken();

        // Deal with the request
        if ($request->isMethod('post'))
        {
            $this->form->bind($request->getParameter("content[%s]"));

            if ($this->form->isValid())
            {
                // Do stuff
                //$this->redirect('foo/bar');
                echo "valid";
            }
            else
            {
                $this->_preWrap($_POST);
            }
        }
    }

Still don't know why it's giving me an error on all fields and why I'm getting the csrf token: Required.

4
I seem to recall that you need to render the hidden fields in your view to get the CSRF fields. The failed binding is likely a CSRF failure.Duane Gran
Symfony requires all forms to have CSRF fields?Charlie
I added the CSRF fields but it still fails. It just says my original fields are required -- despite that they are filled out.Charlie
You can disable CSRF by setting csrf_secret: false in the settings.yml file for your app. Sorry this didn't help though.Duane Gran

4 Answers

4
votes

When you take full control of a Symfony form, as you are doing according to the code snippets in your OP, you will have to manually add the error and csrf elements to your form:

// Manually render an error
<?php if ($form['name']->hasError()): ?>
    <?php echo $form['name']->renderError() ?>
<?php endif ?>

<?php echo $form['name']->renderRow(array('size' => 25, 'class' => 'content'), 'Your Name') ?>

// This will echo out the CSRF token (hidden)
<?php echo $form['_csrf_token']->render() ?>

Check out Symfony Docs on custom forms for more info. Also, be sure to add CSRF back to your form, there is no reason to leave it out, and will protect from outside sites posting to your forms.

1
votes

It might be wise to render any global form errors:

$form->renderGlobalErrors() 
0
votes

Don't you have a typo in your executeComment function ?

    $this->form->getWidgetSchema()->setNameFormat('contact[%s]');

and later:

    $this->form->bind($request->getParameter("content[%s]"));

You should write:

    $this->form->getWidgetSchema()->setNameFormat('content[%s]');

But this line is not necessary you can delete it (the NameFormat is already done in your form class).

And the $request->getParameter("content[%s]") will not word ("content[%s]" is the format of the data sent by the form), you should use:

    $this->form->bind($request->getParameter("content"));

Or best, to avoid this kind of typo:

public function executeComment($request)
{
    $this->form = new ContentForm();
    // Deal with the request
    if ($request->isMethod('post'))
    {
        $this->form->bind($request->getParameter($this->form->getName()));

        if ($this->form->isValid())
        {
            // Do stuff
            //$this->redirect('foo/bar');
            echo "valid";
        }
        else
        {
            $this->_preWrap($_POST);
        }
    }
}
0
votes

I ran into the same problem with an admin generated backend form. When I tried to apply css schema changes with this code, it broke the token. It didn't break right away. That signals to me this is a bug in Symfony 1.4

$this->setWidgetSchema(new sfWidgetFormSchema(array(
      'id'                 => new sfWidgetFormInputHidden(),
      'category'           => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('RidCategories'), 'add_empty' => false)),
      'location_id'        => new sfWidgetFormInputText(),
      'title'              => new sfWidgetFormInputText(array(), array('class' => 'content')),
      'content'            => new sfWidgetFormTextarea(array(), array('class' => 'content')),
      'content_type'       => new sfWidgetFormInputText(),
      'schedule_date'      => new sfWidgetFormInputText(),
      'post_date'          => new sfWidgetFormInputText(),
      'display_status'     => new sfWidgetFormInputText(),
      'parent_id'          => new sfWidgetFormInputText(),
      'keyword'            => new sfWidgetFormInputText(),
      'meta_description'   => new sfWidgetFormInputText(),
      'update_frequency'   => new sfWidgetFormInputText(),
      'keywords'           => new sfWidgetFormInputText(),
      'allow_content_vote' => new sfWidgetFormInputText(),
      'rating_score'       => new sfWidgetFormInputText()
)));