2013-03-11 40 views
0

我有這樣的模式:變化動態validated_file_class symfony的1.4

Banner: 
columns: 
    filename: string(255) 
    url: string(255) 
    position: 
    type: enum 
    values: [top, right] 
    default: right 

這種形式:

class BannerForm extends BaseBannerForm 
{ 
    public function configure() 
    { 
    $this->widgetSchema['filename'] = new sfWidgetFormInputFileEditable(array(
     'file_src' => $this->getObject()->getThumbURL(), 
     'is_image' => true, 
     'edit_mode' => $this->getObject()->exists() 
    )); 
    $validated_file_class = $this->getObject()->position === 'right' ? 'bannerRightValidatedFile' : 'bannerTopValidatedFile'; 
    $this->validatorSchema['filename'] = new sfValidatorFile(array(
     'path' => sfConfig::get('sf_upload_dir'), 
     'mime_types' => 'web_images', 
     'validated_file_class' => $validated_file_class', 
     'required' => $this->getObject()->isNew() 
    )); 
    } 
} 

我用不同的驗證類,因爲它裏面我incapsulate縮略圖操作,和橫幅的尺寸取決於它的位置領域。 問題是$ validated_file_class始終是bannerRightValidatedFile類。 我怎麼能做到這件事?

+0

作爲一種替代解決方案,您可以將圖像調整大小放到'Banner'類的'preSave'或'postSave'方法中,並讓驗證器單獨離開@kirugan – 1ed 2013-03-11 18:16:08

+0

@ 1ed是的,我可以,但我認爲它會導致錯誤代碼 – kirugan 2013-03-11 19:03:28

+0

你爲什麼這麼想?我認爲它比下面提到的驗證程序更簡潔。 – 1ed 2013-03-11 19:09:27

回答

2

我可以建議4個解決方案,您可以選擇:

選項1:

您應該添加更新$ fieldNameColumn方法窗體類。在你的情況下,它應該看起來像這樣:

// change validated file instance before calling save 
protected function updateFilenameColumn($value) 
{ 
    if ($value instanceof sfValidatedFile) 
    { 
    $class = 'right' == $this->getValue('position') ? 'bannerRightValidatedFile' : 'bannerTopValidatedFile'; 
    // this will not work as I thought at first time 
    // $this->getValidator('filename')->setOption('validated_file_class', $class); 

    $this->values['filename'] = new $class(
     $value->getOriginalName(), 
     $value->getType(), 
     $value->getTempName(), 
     $value->getSize(), 
     $value->getPath() 
    ); 

    return $this->processUploadedFile('filename'); 
    } 

    return $value; 
} 

我認爲這是一種哈克。

選項2:

您應該添加教義掛鉤的方法模型:

/** 
* @param Doctrine_Event $event 
*/ 
public function postSave($event) 
{ 
    $record = $event->getInvoker(); 

    if (array_key_exists('filename', $record->getLastModified())) 
    { 
    // get the full path to the file 
    $file = sfConfig::get('sf_upload_dir') . '/' . $record->getFilename(); 

    if (file_exists($file)) 
    { 
     // resize the file e.g. with sfImageTransformPlugin 
     $img = new sfImage($file); 
     $img 
     ->resize(100, 100) 
     ->save(); 
    } 
    } 
} 

創造記錄時whitout形式例如這將工作當使用燈具時。

方案3:

使用admin.save_object事件。

public static function listenToAdminSaveObject(sfEvent $event) 
{ 
    $record = $event['object']; 

    if ($event['object'] instanceof Banner) 
    { 
    // use the same code as in the `postSave` example 
    } 
} 

方案4:

使用sfImageTransformExtraPlugin

這是一種很難設置和配置(以及它的代碼是一個爛攤子:),但它使得可以修改的大小圖像不會再生所有已調整大小的圖像。

+0

非常感謝你的選擇,我會盡快嘗試 – kirugan 2013-03-11 21:33:36

+0

@kirugan有什麼反饋? – 1ed 2013-03-18 22:42:20

+0

對不起,我正忙着回答 – kirugan 2013-03-22 04:07:09

1

您可以添加一個sfCallbackValidator作爲後驗證器,並相應地設置屬性。

僞代碼(我手邊沒有確切的功能簽名)。

public function configure() { 
    // ... 
    $this->mergePostValidator(new sfCallbackValidator(array('callback' => array($this, 'validateFile')))); 
} 

public function validateFile($values) { 
    $realValidator = new sfValidatorFile(...); 
    return $realValidator->clean($values['field']); 
} 
1

如果你可以修改調用窗體類,你可以這樣做:

$form = new BannerForm(array(), array('validated_file_class' => 'bannerRightValidatedFile'); 
$form2 = new BannerForm(array(), array('validated_file_class' => 'bannerTopValidatedFile'); 

然後在您的形式:

class BannerForm extends BaseBannerForm 
{ 
    public function configure() 
    { 
    $this->widgetSchema['filename'] = new sfWidgetFormInputFileEditable(array(
     'file_src' => $this->getObject()->getThumbURL(), 
     'is_image' => true, 
     'edit_mode' => $this->getObject()->exists() 
    )); 

    $this->validatorSchema['filename'] = new sfValidatorFile(array(
     'path'     => sfConfig::get('sf_upload_dir'), 
     'mime_types'   => 'web_images', 
     'validated_file_class' => $this->options['validated_file_class'], 
     'required'    => $this->getObject()->isNew() 
    )); 
    } 
} 

編輯:

既然你在管理gen裏面玩,我認爲最好的辦法是用postValida像@Grad van Horck說的那樣。

您的驗證類取決於額外的字段。使用postvalidator,您可以訪問表單中的任何字段。然後,您只需創建一個小開關來處理每個職位/經過驗證的班級的案例。

public function configure() 
{ 
    // ... 
    $this->mergePostValidator(new sfValidatorCallback(array('callback' => array($this, 'validateFile')))); 
} 

public function validateFile($validator, $values, $arguments) 
{ 
    $default = array(
     'path'  => sfConfig::get('sf_upload_dir'), 
     'mime_types' => 'web_images', 
     'required' => $this->getObject()->isNew() 
    ); 

    switch ($values['position']) { 
     case 'right': 
      $validator = new sfValidatorFile($default + array(
       'validated_file_class' => 'bannerRightValidatedFile', 
      )); 
      break; 

     case 'top': 
      $validator = new sfValidatorFile($default + array(
       'validated_file_class' => 'bannerTopValidatedFile', 
      )); 

     default: 
      # code... 
      break; 
    } 

    $values['filename'] = $validator->clean($values['filename']); 

    return $values; 
} 
+0

嗯......我明白了,但我在管理區使用它,所以我應該改變一些部分文件,創建動作來處理請求,看一些字段,然後創建適當的表單。也許有簡單的方法?我的意思是,如果管理員形式 – kirugan 2013-03-11 16:02:17

+0

嗡嗡聲我看到,它是更復雜的內部管理員沒有修改太多的文件。我認爲postValidator是一個很好的解決方案,我會更新我的答案。 – j0k 2013-03-11 16:16:47