Рецепт только для Symfony 1.2. На других версиях не проверялся.
При работе с формами, если требуется сохранить файлы, то в БД пишется только имя загружаемого файла, например: fa3d2c687c04e411372045106.jpg. Мне удобнее сохранить в БД относительный путь к картинке, так легче работать на выводе, например: /uploads/news/2008/10/16/fa3d2c687c04e411372045106.jpg. Для решения этой задачи требуется указать желаемый путь к директории $this->path в классе NewsForm и переназначить метод saveFile, который используется для записи имени файла в БД. Единственное, что перестанет работать удаление файлов, т.к. путь получается неверный, чтобы это исправить расширяем базовый класс BaseFormPropel и корректируем путь к файлам. Полагаю, что то же самое сработает и для Doctrine.
Листинг 1: Изменяем класс NewsForm.class.php, чтобы переназначить пути к файлам
<?php /** * News form. */ class NewsForm extends BaseNewsForm { public function configure() { parent::configure(); $this->path = 'news/' . date('Y/m/d'); $this->setWidget('image', new sfWidgetFormInputFileEditable(array( 'file_src' => '-foo-', 'is_image' => true ))); $this->validatorSchema['image'] = new myValidatorFile(array( 'required' => false, 'mime_types' => 'web_images', 'path' => sfConfig::get('sf_upload_dir') . $this->path, )); $this->validatorSchema->setOption('allow_extra_fields', true); $this->validatorSchema->setOption('filter_extra_fields', false); } public function saveFile($field, $filename = null, sfValidatedFile $file = null) { return '/uploads/' . $this->path . '/' . parent::saveFile($field, $filename, $file); } }
Листинг 2: Изменяем класс BaseFormPropel.class.php, чтобы сработало удаление файлов
<?php abstract class BaseFormPropel extends sfFormPropel { public function setup() { } /** * Removes the current file for the field. * * @param string $field The field name */ protected function removeFile($field) { if (!$this->validatorSchema[$field] instanceof sfValidatorFile) { throw new LogicException(sprintf('You cannot remove the current file for field "%s" as the field is not a file.', $field)); } $column = call_user_func(array(constant(get_class($this->object).'::PEER'), 'translateFieldName'), $field, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME); $getter = 'get'.$column; if (($directory = sfConfig::get('sf_web_dir')) && is_file($directory.$this->object->$getter())) { unlink($directory.$this->object->$getter()); } } }
Другие ссылки:
• The symfony Forms Book: Chapter 4 – Propel Integration
• SYMFONY 1.2: UPLOAD A FILE INSIDE AN EMBEDDED FORM