Drupal 8:获取并修改内嵌实体表单输入及提交前表单状态值
解决Drupal 8 Inline Entity Form Complex的两个常见问题
刚好我之前在Drupal 8里处理过不少Inline Entity Form(IEF)的场景,针对你提出的两个问题,给你分享下实际可行的解决方案:
问题1:如何获取并修改IEF Complex的用户输入(保存前)
要在保存前获取并修改内嵌实体的用户输入,最可靠的方式是直接操作IEF绑定的实体对象,或者通过表单状态精准获取内嵌表单的值。这里分两种场景给你示例:
方式1:直接修改实体对象(推荐)
IEF的表单是和实体绑定的,你可以在hook_inline_entity_form_entity_form_alter里直接拿到当前的内嵌实体,修改它的字段值,保存时会自动生效:
function mymodule_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { // 确认是你要处理的实体类型 if ($entity_form['#entity_type'] == 'care_giver') { // 获取当前的care_giver实体对象 $care_giver = $entity_form['#entity']; // 示例:将姓名转为大写 if (!empty($care_giver->field_name->value)) { $care_giver->field_name->value = strtoupper($care_giver->field_name->value); } // 其他字段修改同理,比如调整联系方式、状态等 } }
方式2:获取表单输入值并修改(适合复杂场景)
如果需要基于用户提交的原始输入做处理,可以通过表单的#parents属性定位内嵌表单的具体值,避免拿到外层宿主表单的冗余数据:
function mymodule_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { if ($entity_form['#entity_type'] == 'care_giver') { // 获取当前内嵌表单的所有输入值 $ief_input_values = $form_state->getValue($entity_form['#parents']); // 比如获取姓名字段的值 $name = $ief_input_values['field_name'][0]['value']; // 修改后写回表单状态 $ief_input_values['field_name'][0]['value'] = strtolower($name); $form_state->setValue($entity_form['#parents'], $ief_input_values); } }
如果需要在表单验证完成后再做修改,还可以给IEF表单添加自定义提交回调,确保数据是有效的:
function mymodule_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { if ($entity_form['#entity_type'] == 'care_giver') { // 添加自定义提交回调 $entity_form['#submit'][] = 'mymodule_care_giver_ief_post_process'; } } function mymodule_care_giver_ief_post_process(&$form, &$form_state) { $care_giver = $form['#entity']; // 在这里做最终的字段修改或数据处理 $care_giver->field_status->value = 'verified'; // 不需要手动保存,IEF会自动处理实体的保存逻辑 }
问题2:收集IEF数据并保存到另一个实体的问题修复
你之前用$form_state->getUserInput()的问题在于,这个方法返回的是整个表单的原始POST数据,包括外层宿主表单的所有内容,很难精准提取内嵌实体的字段值。这里给你两种正确的处理方式:
方式1:通过实体对象获取数据(推荐)
在IEF的表单提交回调里,直接拿到当前的care_giver实体,读取它的字段值来创建并保存另一个实体:
function mymodule_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { if ($entity_form['#entity_type'] == 'care_giver') { // 添加提交回调,确保在表单验证通过后执行 $entity_form['#submit'][] = 'mymodule_save_care_giver_to_other_entity'; } } function mymodule_save_care_giver_to_other_entity(&$form, &$form_state) { // 获取当前的care_giver实体(新增或编辑的都可以) $care_giver = $form['#entity']; // 示例:创建一个contact实体并保存数据 $contact = \Drupal\contact\Entity\Contact::create(); // 复制care_giver的字段值到contact $contact->field_full_name->value = $care_giver->field_name->value; $contact->field_email->value = $care_giver->field_email->value; $contact->field_phone->value = $care_giver->field_phone->value; // 保存新实体 $contact->save(); }
方式2:通过表单状态获取输入值
如果需要获取用户提交的最新输入(比如实体还没被IEF更新),可以用$form_state->getValue($entity_form['#parents'])定位内嵌表单的具体值:
function mymodule_save_care_giver_to_other_entity(&$form, &$form_state) { // 获取内嵌表单的输入值 $ief_values = $form_state->getValue($form['#parents']); // 提取字段值 $name = $ief_values['field_name'][0]['value']; $email = $ief_values['field_email'][0]['value']; // 创建并保存另一个实体 $contact = \Drupal\contact\Entity\Contact::create([ 'field_full_name' => $name, 'field_email' => $email, ]); $contact->save(); }
注意事项
- 不要在
hook_inline_entity_form_entity_form_alter里直接保存另一个实体,因为此时表单可能还没完成验证,数据可能无效; - 如果是新增的care_giver实体,
$care_giver->id()会是空的,这是正常的,因为它还没被IEF保存到数据库,但字段值已经可以正常读取; - 确保你有权限创建和保存目标实体(比如contact),否则会抛出权限错误。
内容的提问来源于stack exchange,提问作者Ngoni
相关产品推荐
相关产品推荐

