SUBSCRIBE VIA RSS


Subscribe to our feed

Symfony Experts

Symfony Experts
If you have an urgent question for a symfony-related issue, this is the place to ask.

Topics

TWITTER

Stack Overflow


The old fashioned way

RECENT TUNES

October 4, 2009 – 1:19am Symfony, Doctrine Upload File “validation failed”

After setting up a simple file upload using the symfony 1.2 forms class and a doctrine model, I hit this error right away:

500 | Internal Server Error | Doctrine_Validator_Exception
 1 field had validation error:
 * 1 validator failed on file (type)

The short solution: when using a doctrine form class and $form->save(), set the path option in your sfValidatorFile validator and do not attempt to save/set the file column yourself. If you are curious why this is, continue reading.

What was particularly strange about this error is that the “file” column in my model was defined as a string, and I was certain I was setting this column by hand to the file name (a string) of the uploaded file. Hmm… this shouldn’t trigger an error, should it? This following is what did not work. I used the documentation for sfValidatorFile() found in the symfony Forms book.

// my form
class ArtistForm extends BaseArtistForm
{
  public function configure()
  {
    $this->widgetSchema['file'] = new sfWidgetFormInputFile();
    $this->validatorSchema['file'] = new sfValidatorFile(array(
      'required' => false, 'mime_types' => 'web_images'
    ));
  }
}
 
// my action ***did not work***
public function executeForm(sfWebRequest $request)
  {
    $this->form = new ArtistForm();
    if ($request->isMethod('post')) {
      $this->form->bind($request->getParameter('artist'), $request->getFiles('artist'));
      if ($this->form->isValid())
      {
        $file = $this->form->getValue('file');
        if ($file) {
          $filename = sha1($file->getOriginalName());
          $extension = $file->getExtension($file->getOriginalExtension());
          $file->save(sfConfig::get('sf_upload_dir').'/'.$filename.$extension);          
          $this->form->getObject()->setFile($filename.$extension);
        }
 
        $this->form->save();
      }
    }    
  }

Anytime I’d try to upload a file, I’d get the dreaded “Doctrine_Validator_Exception”, “validator failed on file (type)” message. After some serious googling, I came up with a few links (listed at the bottom of this post) that eventually led me to the solution. The issues boils down to this:

  • When using the sfValidatorFile widget in your form, retrieving that value from your form returns an sfValidatedFile object
  • Doctrine forms will automatically try to process and save uploaded files, so you do not need to do this manually in your action if you call $form->save() and your form contains an instance of sfValidatorFile
  • The automatic save mechanism in your doctrine form will fail if you do not define a path in your sfValidatorFile validator. This is because if no path is defined in your validator, the validator returns an instance of sfValidatedFile and calling $form->save() will result in trying to update your doctrine object with this sfValidatorFile instance, resulting in an error.
  • If a path is defined in your sfValidatorFile validator, the bound form value for your file input field is set to the full path to saved file rather than an sfValidatedFile instance, allowing your doctrine object to be saved.

Now, with a deeper understanding of how this is all put together, we can update our action:

// doctrine form class
class ArtistForm extends BaseArtistForm
{
  public function configure()
  {
    $this->widgetSchema['photo'] = new sfWidgetFormInputFile();
    $this->validatorSchema['photo'] = new sfValidatorFile(array(
      'required' => false, 'mime_types' => 'web_images',
      'path' => sfConfig::get('sf_upload_dir')
    ));
  }
}
 
// the action
  public function executeForm(sfWebRequest $request)
  {
    $this->form = new ArtistForm();
    if ($request->isMethod('post')) {
      $this->form->bind($request->getParameter('artist'), $request->getFiles('artist'));
      if ($this->form->isValid())
      {
        $this->form->save();
      }
    }    
  }

More about this issue in the forums and mailing list:

Posted by in  Web Development   |  

3 Responses to Symfony, Doctrine Upload File “validation failed”

  1. lightpriest says:

    Thanks for enlightening on the subject. It did the trick for me.

    I’ve experienced the same problem as well, and symfony’s lack of a comprehensive reference only made it worse.

    In my case, I needed to save a constant filename rather then a generated one.
    Took me while to figure out I had pass that filename along with the path in the ‘new sfValidator()’ call.

  2. Cindy says:

    Thanks for this!!! Saved me a ton of time!

  3. Sanya says:

    The most frustrating thing is: you cannot define a custom sfWidgetFormInputFile widget if your form is a descendant of sfDoctrineForm.
    It will return a “unknown field” error if you do so…

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>