Elementor表单字段按属性分配数组失败,求代码修复
问题:Elementor表单无法根据field_attribute分类字段到ADF XML节点
我在Elementor表单中添加了自定义的field_attribute字段(用于标记字段属于vehicle/customer/vendor),但无法根据该属性值将表单字段分配到对应的数组,最终生成的ADF XML不符合预期——无法将Model(设为vehicle)、Name(设为customer)、Phone(设为vendor)分别放入对应的<vehicle>、<customer>、<vendor>节点中。
错误核心代码片段
global $selected_option; // ... if ( $selected_option === 'vehicle' ) { $vehicleFields[] = [$field_name => $field_value]; } // ...
问题原因分析
- 全局变量使用错误:在
maybe_add_attribute方法中,每次处理字段都会重置$selected_option = array();,导致最终只保留最后一个字段的属性值,且为数组类型,后续$selected_option === 'vehicle'的判断永远不成立。 - 字段与属性未关联:在
new_record钩子中,没有将每个字段的field_attribute和对应值绑定,无法区分单个字段的属性分类。 - 遍历逻辑错误:分类判断代码不在字段循环内,无法逐个处理每个表单字段。
修复后的完整代码
<?php class Elementor_Forms_Patterns_Validation { public $allowed_fields = [ 'text', 'email', 'textarea', ]; public function __construct() { add_action( 'elementor/element/form/section_form_fields/before_section_end', [ $this, 'add_attribute_field_control' ], 100, 2 ); // 改用form_fields_registered钩子存储字段属性,避免渲染阶段的全局变量问题 add_action( 'elementor_pro/forms/form_fields_registered', [ $this, 'store_field_attributes' ], 10, 1 ); } public function add_attribute_field_control( $element, $args ) { $elementor = \Elementor\Plugin::instance(); $control_data = $elementor->controls_manager->get_control_from_stack( $element->get_name(), 'form_fields' ); if ( is_wp_error( $control_data ) ) { return; } $tmp = new \Elementor\Repeater(); $tmp->add_control( 'field_attribute', [ 'label' => 'Attribute', 'inner_tab' => 'form_fields_advanced_tab', 'tab' => 'content', 'tabs_wrapper' => 'form_fields_tabs', 'type' => 'select', 'options' => [ '' => 'None', 'vehicle' => 'vehicle', 'customer' => 'customer', 'vendor' => 'vendor', ], 'conditions' => [ 'terms' => [ [ 'name' => 'field_type', 'operator' => 'in', 'value' => $this->allowed_fields, ], ], ], ] ); $attribute_field = $tmp->get_controls(); $attribute_field = $attribute_field['field_attribute']; $new_order = []; foreach ( $control_data['fields'] as $field_key => $field ) { if ( 'custom_id' === $field['name'] ) { $new_order['field_attribute'] = $attribute_field; } $new_order[ $field_key ] = $field; } $control_data['fields'] = $new_order; $element->update_control( 'form_fields', $control_data ); } // 存储表单字段的属性映射,键为字段名称(或custom_id),值为field_attribute public function store_field_attributes( $form ) { $form_settings = $form->get_settings_for_display(); if ( empty( $form_settings['form_fields'] ) ) { return; } $field_attributes = []; foreach ( $form_settings['form_fields'] as $field ) { $field_name = ! empty( $field['custom_id'] ) ? $field['custom_id'] : $field['field_label']; $field_name = str_replace( ' ', '_', $field_name ); if ( isset( $field['field_attribute'] ) && ! empty( $field['field_attribute'] ) ) { $field_attributes[ $field_name ] = $field['field_attribute']; } } // 将属性映射存储到表单实例,方便后续钩子调用 $form->field_attributes = $field_attributes; } } // Convert Elementor form data to ADF format and send email add_action( 'elementor_pro/forms/new_record', function( $record, $handler ) { // Get form data and form name $data = $record->get_formatted_data(); $form_id = $record->get_form_settings( 'form_id' ); $form_name = $record->get_form_settings( 'form_name' ); // 获取存储的字段属性映射 $field_attributes = $handler->form->field_attributes ?? []; $vehicleFields = []; $customerFields = []; $vendorFields = []; // 遍历每个字段,根据属性分类 foreach ( $data as $field_label => $field_value ) { // 替换空格为下划线,和存储的键保持一致 $field_name = str_replace( ' ', '_', $field_label ); // 获取当前字段的属性 $selected_option = $field_attributes[ $field_name ] ?? ''; if ( $selected_option === 'vehicle' ) { $vehicleFields[] = [ $field_name => $field_value ]; } elseif ( $selected_option === 'customer' ) { $customerFields[] = [ $field_name => $field_value ]; } elseif ( $selected_option === 'vendor' ) { $vendorFields[] = [ $field_name => $field_value ]; } } // Generate ADF XML $xml = new DOMDocument( "1.0", "UTF-8" ); $adf = $xml->createElement( "adf" ); $prospect = $xml->createElement( "prospect" ); // Add request date to prospect $requestdate = $xml->createElement( "requestdate", date( 'c' ) ); $prospect->appendChild( $requestdate ); // Add vehicle data to prospect if ( ! empty( $vehicleFields ) ) { $vehicle = $xml->createElement( "vehicle" ); foreach ( $vehicleFields as $field ) { foreach ( $field as $field_name => $field_value ) { $fieldElement = $xml->createElement( $field_name, $xml->createTextNode( $field_value ) ); $vehicle->appendChild( $fieldElement ); } } $prospect->appendChild( $vehicle ); } // Add customer data to prospect if ( ! empty( $customerFields ) ) { $customer = $xml->createElement( "customer" ); $contact = $xml->createElement( "contact" ); foreach ( $customerFields as $field ) { foreach ( $field as $field_name => $field_value ) { $fieldElement = $xml->createElement( $field_name, $xml->createTextNode( $field_value ) ); $contact->appendChild( $fieldElement ); } } $customer->appendChild( $contact ); $prospect->appendChild( $customer ); } // Add vendor data to prospect if ( ! empty( $vendorFields ) ) { $vendor = $xml->createElement( "vendor" ); $contact = $xml->createElement( "contact" ); foreach ( $vendorFields as $field ) { foreach ( $field as $field_name => $field_value ) { $fieldElement = $xml->createElement( $field_name, $xml->createTextNode( $field_value ) ); $contact->appendChild( $fieldElement ); } } $vendor->appendChild( $contact ); $prospect->appendChild( $vendor ); } $adf->appendChild( $prospect ); $xml->appendChild( $adf ); // Format ADF XML for readability $xml->formatOutput = true; $adf_xml = $xml->saveXML(); // Send email with ADF XML in body $to = array( 'example@mail.com'); $subject = 'Subject '; $headers = array( 'Content-Type: text/plain; charset=UTF-8', 'From: From <email@example.com>' ); wp_mail( $to, $subject, $adf_xml, $headers ); }, 10, 2 ); new Elementor_Forms_Patterns_Validation();
关键修改说明
- 移除全局变量:改用
elementor_pro/forms/form_fields_registered钩子将字段属性存储到表单实例中,避免全局变量的覆盖问题。 - 关联字段与属性:在字段循环中,通过处理后的字段名匹配对应的
field_attribute,实现每个字段的精准分类。 - XML安全处理:使用
createTextNode()包裹字段值,避免特殊字符破坏XML结构。 - 优化逻辑结构:删除无用的前端渲染钩子,专注后端属性存储与分类逻辑。
内容的提问来源于stack exchange,提问作者Hussain Ahmed
相关产品推荐
相关产品推荐

