2012-02-13 119 views
1

我有一組項目,我可以使用表單進行編輯和刪除。現在,所有itms都以字段集的形式顯示在列表中。Drupal刪除/更新數據庫中的錯誤行

$venues = db_query('SELECT vid, name, address, postcode, city FROM venues v WHERE v.uid = :uid', array(':uid' => $user->uid)); 
if($venues->rowCount() != 0) { 
    foreach($venues as $venue) { 
    $page['venue_editing_form'][] = drupal_get_form('venue_editor_form', $venue->vid, $venue->name, $venue->address, $venue->postcode, $venue->city); 
    } 
} 

然後形式與此函數創建:

function venue_editor_form($form, &$form_state, $vid, $vname, $vadd, $vpostc, $vcity) { 
$form['#prefix'] = '<div class="vedit">'; 
$form['#suffix'] = '</div>'; 
$form['edit_fieldset_'.$vname] = array(
    '#type' => 'fieldset', 
    '#title' => t($vname), 
    '#collapsible' => TRUE, 
    '#collapsed' => TRUE, 
    '#attributes' => array('class' => array('venue-edit')), 
); 
$form['edit_fieldset_'.$vname]['venue_name'] = array(
    '#type' => 'textfield', 
    '#title' => t('Venue name:'), 
    '#description' => t('Enter the venue name.'), 
    '#default_value' => $vname, 
    '#attributes' => array('onfocus' => 'this.value=""') 
); 
$form['edit_fieldset_'.$vname]['address'] = array(
    '#type' => 'textfield', 
    '#title' => t('Address:'), 
    '#description' => t('The address of this venue.'), 
    '#default_value' => $vadd, 
    '#attributes' => array('onfocus' => 'this.value=""') 
); 
$form['edit_fieldset_'.$vname]['postcode'] = array(
    '#type' => 'textfield', 
    '#title' => t('Postcode'), 
    '#description' => t('Enter the postcode for this event, so planB can position it on the map'), 
    '#default_value' => $vpostc, 
    '#attributes' => array('onfocus' => 'this.value=""', 'onblur' => 'getLatLong(this)') 
); 
$form['edit_fieldset_'.$vname]['city'] = array(
    '#type' => 'textfield', 
    '#title' => t('City'), 
    '#description' => t('The city this venue is in.'), 
    '#default_value' => $vcity, 
    '#attributes' => array('onfocus' => 'this.value=""') 
); 
$form['edit_fieldset_'.$vname]['edit_submit'] = array(
    '#type' => 'submit', 
    '#value' => t('Submit changes'), 
    '#validate' => array('venue_creation_form_validate') 
); 
$form['edit_fieldset_'.$vname]['delete_venue'] = array(
    '#type' => 'submit', 
    '#value' => t('Delete venue'), 
    '#submit' => array('venue_form_delete') 
); 
$form['edit_fieldset_'.$vname]['venueid'] = array(
    '#type' => 'value', 
    '#value' => $vid 
); 
return $form; 

}

並提交處理程序之一:

function venue_form_delete($form, &$form_state) { 
    $deleted = db_delete('venues') 
    ->condition('vid', $form['#venueid'], '=') 
    ->execute(); 
    drupal_set_message('Venue deleted successfully.'); 
} 

的字段集用這種方法創建現在,問題是無論按下哪個場所的刪除按鈕,Drupal都會刪除第一個列表中的那些人。 $form['#venueid']總是設置爲提交處理程序列表中的第一個場所,但出於某種原因,如果在生成表單時打印消息,則每個表單都應有不同的ID。

有沒有人有過這個問題?

+0

vid從哪裏來?你的意思是NID嗎? – SpaceBeers 2012-02-14 07:32:46

+0

vid是它來自數據庫查詢以獲取所有場所的詳細信息的場所ID。然後,我使用一個foreach循環遍歷所有結果和drupal_get_form('venue_editor_form',$ venue-> vid ...) – KerrM 2012-02-14 13:43:10

+0

重讀這個問題,難道是你有一個表單,有多個字段集和多個Submit /刪除按鈕(即每個場地一個字段集)? – 2012-02-14 17:23:54

回答

1

幾周前,我的一位同事遇到了這個問題。您遇到此問題的原因是因爲您嘗試在具有不同數據的頁面上多次加載相同的表單。看起來這應該起作用,但它並不是因爲所有表單都以相同的標記/ ID結束。當您提交每個表單時,系統不知道您真正點擊了哪個表單,並且無法採取適當的措施。

有解決這個問題的方法2:

1)返工您的形式,使其所有與1點的形式,而不是多個

2)使用hook_forms(...)創建「基本形式」和處理然後爲映射到「基本形式」的每個場地生成獨特的表格。這將確保每個表單都可以獲得唯一的ID,而無需爲每個表單編寫表單。

我沒有drupal 7的例子,但這裏是一個頁面,展示瞭如何使用hook_forms http://www.computerminds.co.uk/drupal-6-multiple-instances-same-form-one-page來解決drupal 6的問題。你應該能夠運用同樣的技術

我還沒有測試此代碼,但是這是基本的想法:

修改您的get_form使用一個唯一的ID

foreach($venues as $venue) { 
    $page['venue_editing_form'][] = drupal_get_form('venue_editor_form_'. $venue->vid, $venue->vid, $venue->name, $venue->address, $venue->postcode, $venue->city); 
    } 

Impliment hook_forms

function MODULENAME_forms($form_id) { 
    $forms = array(); 
    if (preg_match('/venue_editor_form_/', $form_id) { 
    $forms[$form_id] = array(
     'callback' => 'venue_editor_form', 
    ); 
    } 
    return $forms; 
} 

然後我認爲你必須修改你的表單的提交參數,以確保它們都被路由到相同的提交處理程序。雖然它看起來像要添加,每個按鈕不同的提交,所以你可能沒有做任何有

$form['#submit'] => array('venue_editing_form_submit'); 

您可能還必須做同樣與驗證功能。

這應該做到這一點。

+0

謝謝,這解決了這個問題。 Drupal無法辨別具有相同表單ID的提交內容,這就是爲什麼它會刪除錯誤的地點!再次感謝。 – KerrM 2012-02-17 13:52:23

0

我想這個問題是在您嘗試通過表單處理的venueid值,而不使用一個明確的價值領域:

$form['#venueid'] = $vid; 

這只是一個值分配給「由」形式的財產(主要'#'),通常不存在。嘗試使用一個明確的value field type代替:

$form['venueid'] = array(
    '#type' => 'value', 
    '#value' => $node->vid 
); 

這樣,VID應該在你提交的功能,就像任何其他形式的價值,即可以在$form_state['values']

function venue_form_delete($form, &$form_state) { 
    $deleted = db_delete('venues') 
    ->condition('vid', $form_state['values']['venueid'], '=') 
    ->execute(); 
    drupal_set_message('Venue deleted successfully.'); 
} 

注意去除'#'字符 - 前導'#'表示表單(和表單元素)屬性,Drupal將在表單處理期間嘗試解釋這些屬性,並且'#venueid'不是定義的屬性。

+1

使用自定義FAPI屬性是非常標準的做法(許多貢獻的模塊都是這樣做的,例如Date的'#date_format'鍵)。在數組中使用'#''d屬性的唯一問題是可能與現有命名屬性發生衝突。這可以通過在屬性名稱前加上負責實現它的模塊名稱來避免,例如'#mymodule_venueid'。除此之外,這種方法是100%有效的,不會導致所描述的問題。 – Clive 2012-02-14 12:50:00

+2

@Clive:你說得對,很多contrib模塊都是這樣做的,但我不會稱之爲'標準實踐'。使用像這樣的FAPI屬性意味着依賴一個未公開的功能(可以隨時更改),而不是使用官方的,記錄的和推薦的替代(以'#value'類型元素的形式)。因此,我的建議旨在首先嚐試「正常」方式,然後再尋找無證「特徵」的問題。 – 2012-02-14 16:36:33

+1

@Clive:爲了避免誤解 - 「無證」,我並不是指自定義FAPI屬性的概念。如果想從自定義模塊擴展FAPI功能,例如通過提供一個新的元素類型,他可以並且應該使用自定義屬性(如日期模塊用'#date_format')。但是,這種屬性的用法是針對表單生命週期中的表單元素處理/處理,而不是傳遞值來提交函數。 – 2012-02-14 17:34:43