2011-08-19 108 views
3

首先,讓我說,我發現sfFormPropel窗體的接口不一致。 有bind(),它不返回任何內容,但會觸發驗證,save()返回保存的對象,bindAndSave()返回布爾值,實際返回值爲isValid()。現在,我有一個工作的應用程序,但我不覺得代碼是正確的,我對symfony很新,所以也許我錯過了一些東西。Symfony/propel窗體保存具有其他屬性的對象

我需要創建的對象需要一些外部屬性,它們不在表單中提供,它們在模型外部,由應用程序處理(例如,用戶的userId,創建實體,外部生成的guid等)。

眼下流程如下:

  • 從請求獲取值並結合他們形成
  • 檢查的形式是有效
  • ,如果它是有效的,增加附加值,並結合他們形成一個更多的時間
  • 保存表單,並返回對象

答案顯然會增加專用值從請求中檢索,但如果表單無效,則綁定特定於應用程序的值是沒有意義的,因爲它們可能會是潛在的昂貴操作,可能會創建數據庫記錄等。此外,它應該不能將這些值與帖子請求通過,它們只能來自應用程序。

現在,雖然我必須讓模型執行這些操作,但由於數據是模型外部的,因此操作仍然需要將它傳遞給模型。問題是,如果我在bind()之後撥打$form->getObject(),它仍然有舊數據,而沒有提交數據。

實施這種後期處理的正確方法是什麼?

二賞金開始批出其他有價值的答案

回答

1

它的種類取決於誰擁有關於額外屬性的「知識」。如果它們確實是特定於請求的,因此需要在控制器中進行處理,我會進行綁定,如果有效則進行測試,然後更新綁定對象。要獲取帶有綁定(和驗證)字段的更新對象,請使用updateObject函數。

$form->bind(..) 
if ($form->isValid()) { 

    $obj = $form->updateObject(); // Updates the values of the object with the cleaned up values. (returns object) 
    $obj->foo = 'bar'; 

    $obj->save(); 
} 

但由於這通常也是形式特定的行爲,我通常會重寫Form類。通過覆蓋doUpdateValues()函數,您可以輕鬆訪問提交的數據,並追加自己的數據。當然你也可以在鏈中更高,並覆蓋save()函數。 要爲此表單設置自定義數據,您還可以「發佈」公共方法,然後由控制器使用。

+0

控制器有知識 - 其中一個值是當前用戶ID(可以很容易地設置爲表單),另一個是通過調用另一個模型生成和檢索的ID(我不想執行該操作呼叫是提交的表單無效),並且未來可能會添加其他模型檢索的其他值。問題是如何更新綁定對象而不觸發已處理字段的驗證? –

+0

您是否嘗試過調用'doUpdateObject()'來獲取'綁定'對象? (見我更新的答案) –

+0

它的工作原理和代碼現在更清潔。謝謝。 processValues()在其他情況下對我很有用。我會把問題和賞金留到星期五,其他建議也歡迎。 –

2

正確的方法將要傳遞給表單構造的對象上設置的默認值。例如,如果你想設置用戶ID登錄要創建一個對象:

$article = new Article(); 
$article->setUserId($this->getUser()->getId()); 
$form = new ArticleForm($article); 
if ($request->isMethod('post')) { 
    $form->bind($request->getParameter('article')); 
    if ($form->isValid()) { 
    $form->save(); 
    } 
} 

同樣,對於現有的對象,你可以加載記錄,並把它傳遞給表單構造改變之前的任何屬性。

編輯:

如果你想驗證後修改的對象,你可以用$形式 - > updateObject()之類梯度表明在他的迴應。如果生成的值取決於提交的值,你可以重寫sfFormObject :: processValues():你需要從動作的東西

class UserForm { 

    public function processValues($values) { 
    $values['hash'] = sha1($values['id'] . $values['username']); 
    return parent::processValues($values); 
    } 

} 

在情況下,你可以隨時把它作爲一個選項的形式:

$form = new UserForm($user, array('foo' => $bar)); 

這樣,您可以在表單代碼中的任何位置使用$ this-> getOption('foo'),例如。在processValues()中。

+0

感謝您參與討論。這仍然需要在保存對象之前生成GUID,並且該對象可能永遠不會被保存。如果值取決於表單中提交的數據(例如,輸入標籤),並根據所有輸入的單詞生成散列(僅舉例),該怎麼辦?也許在某種程度上,模型必須改變以允許這種情況發生。 ubdateObject()在PropelForm中做什麼?也許doSave()的形式必須被覆蓋? –

+0

我編輯了我的回覆。 – Gerry

相關問題