Handling Uploaded file in symfony’s admin generator


When a file is uploaded using sfForm in the admin generator, by default the filename that’s used is a random string, which can look bad in URLs. If you want to change this, it’s not immediately obvious how – but it is incredibly simple.

I think this is perhaps just a badly documented feature; or if it is documented I’ve not ever seen the document, and it doesn’t come up in my search results when I look. A page does document it on the wiki, however it’s rather long winded – http://trac.symfony-project.org/wiki/HowToRenameFileAfterUpload. I found this by accident whilst looking in the sfDoctrinePlugin (the same feature exists in sfPropelPlugin) source code for something else, and here’s the magic:

<?php
abstract class sfFormDoctrine extends sfFormObject
 
  ...
 
  protected function saveFile($field, $filename = null, sfValidatedFile $file = null)
  {
    if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
    {
      throw new LogicException(sprintf('You cannot save the current file for field "%s" as the field is not a file.', $field));
    }
 
    if (null === $file)
    {
      $file = $this->getValue($field);
    }
 
    $method = sprintf('generate%sFilename', $this->camelize($field));
 
    if (null !== $filename)
    {
      return $file->save($filename);
    }
    else if (method_exists($this, $method))
    {
      return $file->save($this->$method($file));
    }
    else if (method_exists($this->getObject(), $method))
    {
      return $file->save($this->getObject()->$method($file));
    }
    else if (method_exists($this->getObject(), $method = sprintf('generate%sFilename', $field)))
    {
      // this non-camelized method name has been deprecated
      return $file->save($this->getObject()->$method($file));
    }
    else
    {
      return $file->save();
    }
  }

From this, you should realise that before saving a file, the admin generator will try looking in a number of places to find out if you’ve defined a method to provide a name, and if you haven’t, it calls back to using a name generated by sfValidatedFile. One of the places you can see it checking is the form, so… try this:

class DownloadForm extends BaseDownloadForm
{
 
  ...
 
  public function generatePreviewImageFilename($validator)
  {
    echo "<pre>";
    var_dump($this->getValues());
    var_dump($validator);
    var_dump($this->getObject()->toArray());
    die();
  }
}

Yes – I’ll admit the way I debug and play with code is very primitive using var_dump’s and dies – but it works for me! This example assume there’s a ‘preview_image’ property of my Download model, but it shows you what variables you have available to you to use to name your file. One think to note is that this is called before save() is called on your object, so if it’s a new object, the Id won’t be available. Other than that, you can name it anything you want. Don’t forget it’s worth ensuring you’re not overwriting an existing file too.

Conclusion

Not every feature of symfony is documented, it would be near impossible to do so too. You could argue the documentation could be better (and I’m sure patches are welcome!) – but really, you will learn more about what you can do by getting your hands dirty and diving into the symfony source code


Leave a comment

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=""> <s> <strike> <strong>

6 thoughts on “Handling Uploaded file in symfony’s admin generator