Рецепт только для 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
Февраль 22nd, 2009 at 11:59
а ничего что new sfWidgetFormInputFileEditable требует обязательный параметр file_src ?
пример не соответствует реально работающей форме
Февраль 22nd, 2009 at 20:50
Верное замечание :), спасибо, подправил.
Апрель 30th, 2009 at 18:17
я еще новичок
сделал по вашему примеру, чето как писал файлы в uploads так и пишет…и ошибок никаких не выводит..
подскажите мож настроить чтото надо
Май 2nd, 2009 at 13:47
Покажите полный пример Вашего кода.
Май 3rd, 2009 at 09:17
меня интересует точное расположение этих файлов, кторые редактируются, потому как в своих я правлю ,а такое чувство что они даже не выполняются
/lib/form/ContentViewForm.class.php
и
/lib/form/baseFormpropel.class.php
код в 1
class ContentViewForm extends BaseContentViewForm
{
parent::configure();
$this->path = ‘view/’ . date(‘Y/m/d’);
$this->setWidget(‘file’, new sfWidgetFormInputFileEditable(array(
‘file_src’ => ‘-foo-‘,
‘is_image’ => true
)));
$this->validatorSchema[‘file’] = 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);
}
}
во втром
abstract class BaseFormPropel extends sfFormPropel
{
public function setup()
{
}
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());
}
}
}
Май 4th, 2009 at 10:26
Вот такой должен быть пример. Это класс NewsForm. Этого вполне достаточно.
class NewsForm extends BaseNewsForm
{
public function configure()
{
parent::configure();
$this->path = ‘news/’ . date(‘Y/m/d’);
$this->setWidget(‘file’, new sfWidgetFormInputFile(),);
$this->validatorSchema[‘file’] = new sfValidatorFile(array(
‘required’ => false,
‘path’ => $this->path,
‘mime_types’ => ‘web_images’,
))
$this->setWidget(‘image_url_1’, sfCpanelForm::getWidgetFormInputFileEditable());
$this->validatorSchema[‘image_url_1’] = sfCpanelForm::getsfValidatorFile($this->path, 1024000);
}
public function saveFile($field, $filename = null, sfValidatedFile $file = null)
{
return ‘/uploads/’ . $this->path . ‘/’ . parent::saveFile($field, $filename, $file);
}