Drupal FAPI drupal_array_set_nested_value 錯誤
情境
有時候我們總需要使用 hook_form_alter 將現有的 form elements 進行一些改變或是增加欄位 ,所以我新增了一個自訂的 AJAX 讓它 return 一個 from 給我,可是只要當前頁面 return 兩次以上,或是當前的 form 有錯誤並且再按送出就會有以下的錯誤
Warning:Illegal string offset 'und' at drupal_array_set_nested_value()
Error:Cannot create references to/from string offsets nor overloaded objects at drupal_array_set_nested_value()
這個錯誤,並不是我程式寫錯而是東西丟給 drupal 核心內的錯誤,更是提高了 debug 的難度阿。
開始漫長的 debug 之路
function MYMODULE_form_commerce_checkout_form_alter(&$form, &$form_state, $form_id){
// Add the form element for selecting a saved address.
$form[$pane_id]['my_save_profile_options'] = array(
'#type' => 'radios',
'#title' => t('My Addressbook'),
'#options' => MYMODULE_options($profiles),
'#weight' => -100,
'#ajax' => array(
'callback' => 'MYMODULE_form_refresh',
'wrapper' => 'customer-profile-' . $key . '-ajax-wrapper',
'method'=>'replace',
),
);
}
function MYMODULE_form_refresh($form, &$form_state)
{
$pane_id = $form_state['triggering_element']['#parents'][0];
$profile_id=$form_state['values']['customer_profile_recipient']['my_save_profile_options'];
$profile=commerce_customer_profile_load($profile_id);
// Add replace element as default AJAX command.
$form['customer_profile_recipient']['field_billing_name']['und'][0]['value']['#value']=$profile->field_billing_name['und'][0]['value'];
$form['customer_profile_recipient']['field_billing_phone']['und'][0]['value']['#value']=$profile->field_billing_phone['und'][0]['value'];
$form['customer_profile_recipient']['field_billing_address']['und'][0]['value']['#value']=$profile->field_billing_address['und'][0]['value'];
$form['customer_profile_recipient']['my_save_profile_options'][$profile_id]['#value']=null;
return $form['customer_profile_recipient'];
}
最後最後發覺問題是在 return $form['customer_profile_recipient'];
這行,只要我 return $form['customer_profile_recipient'];
就會錯誤,只好去看一下 drupal_array_set_nested_value
drupal_array_set_nested_value(array &$array, array $parents, $value, $force = FALSE)
讓我們看到最後一個參數 $force
$force: (Optional) If TRUE, the value is forced into the structure even if it requires the deletion of an already existing non-array parent value. If FALSE, PHP throws an error if trying to add into a value that is not an array. Defaults to FALSE.
所以我們可以得知 form submit 有使用這個 function 來做一些事情,可是問題出在那呢?意思就是當我進到資料庫,你給我的東西不符合我的格式我就會噴錯誤給你,如果設定為 TRUE 就會轉換成相容的格式
舉個例子:我要的可能是字串可是你給我的是陣列
也是有人在討論這個 issues 如 Cannot create references to/from string offsets nor overloaded objects 也有寫了一個 patch 去更改預設為 TRUE 就解決了以上的問題了,打 patch 去更改核心的 code 不是很安全,久了忘了一更新就炸了,特別在此紀錄一下。