前端使用acf_form时如何展示WooCommerce商品字段与元数据
我正在使用ACF搭建前端表单,供供应商角色用户提交商品,表单提交后会自动生成全新的WooCommerce商品。
当前使用的表单配置代码如下:
$options = array( 'post_id' => 'new_post', 'post_title' => true, 'post_content' => true, 'new_post' => array( 'post_type' => 'product', 'post_status' => 'draft' ), 'field_groups' => [$my_field_group_id_created_in_acf], 'form' => true, 'return' => '%post_url%', 'html_submit_button' => '<input type="submit" value="%s" />', 'updated_message' => 'Product Created', 'submit_value' => 'Submit Product' ); acf_form($options);
目前表单默认只输出标题字段、内容编辑器、自行配置的ACF字段组内容,WooCommerce原生的价格、促销价、商品分类、标签这类核心商品字段,还有非ACF创建的自定义元字段都不会自动加载显示。
acf_form() 默认只会渲染ACF自身注册的字段、以及手动开启的post_title/post_content这类基础文章字段,不会自动拉取WooCommerce的商品元字段,分两步处理即可实现需求:
1. 手动在表单中插入需要的原生/自定义字段
可以通过ACF提供的位置钩子,在ACF字段输出的对应位置插入非ACF字段,常用两个钩子:
acf/form/before_fields:在所有ACF字段之前输出内容acf/form/after_fields:在所有ACF字段之后、提交按钮之前输出内容
举个例子,插入常规售价、促销价、商品分类下拉、商品标签输入框的代码可以直接放到主题的functions.php中:
// 在ACF表单末尾追加WooCommerce原生商品字段 add_action('acf/form/after_fields', function() { // 替换成你商品提交表单所在页面的ID,避免影响其他页面的ACF表单 if (!is_page(123)) return; $regular_price = isset($_POST['_regular_price']) ? sanitize_text_field($_POST['_regular_price']) : ''; $sale_price = isset($_POST['_sale_price']) ? sanitize_text_field($_POST['_sale_price']) : ''; ?> <div class="acf-field acf-field-number"> <div class="acf-label"> <label for="_regular_price">常规售价</label> </div> <div class="acf-input"> <input type="number" step="0.01" name="_regular_price" id="_regular_price" value="<?php echo esc_attr($regular_price); ?>"> </div> </div> <div class="acf-field acf-field-number"> <div class="acf-label"> <label for="_sale_price">促销价</label> </div> <div class="acf-input"> <input type="number" step="0.01" name="_sale_price" id="_sale_price" value="<?php echo esc_attr($sale_price); ?>"> </div> </div> <div class="acf-field acf-field-taxonomy"> <div class="acf-label"> <label for="product_cat">商品分类</label> </div> <div class="acf-input"> <?php wp_dropdown_categories([ 'taxonomy' => 'product_cat', 'name' => 'product_cat[]', 'id' => 'product_cat', 'multiple' => true, 'hide_empty' => false, 'hierarchical' => true, ]); ?> </div> </div> <div class="acf-field acf-field-text"> <div class="acf-label"> <label for="product_tags">商品标签</label> </div> <div class="acf-input"> <input type="text" name="product_tags" id="product_tags" placeholder="多个标签用英文逗号分隔"> </div> </div> <?php });
其他非ACF创建的自定义元字段,也可以参照上面的HTML结构自行编写input插入到表单对应位置,字段name属性和存储元数据的meta_key保持一致即可。
2. 表单提交后保存自定义字段数据
ACF默认不会处理手动添加的非ACF字段,需要挂载acf/save_post钩子,在文章创建完成后把这些字段的数据存到对应位置,注意优先级要设为20,等ACF完成基础文章创建逻辑后再执行:
add_action('acf/save_post', function($post_id) { // 排除后台编辑、其他表单提交场景,只处理前台新建商品的提交 if (get_post_type($post_id) !== 'product' || is_admin()) return; // 保存价格数据 if (isset($_POST['_regular_price'])) { update_post_meta($post_id, '_regular_price', wc_clean(wp_unslash($_POST['_regular_price']))); } if (isset($_POST['_sale_price'])) { update_post_meta($post_id, '_sale_price', wc_clean(wp_unslash($_POST['_sale_price']))); } // 保存商品分类 if (isset($_POST['product_cat']) && is_array($_POST['product_cat'])) { $cat_ids = array_map('intval', $_POST['product_cat']); wp_set_object_terms($post_id, $cat_ids, 'product_cat'); } // 保存商品标签 if (isset($_POST['product_tags'])) { $tags = array_map('trim', explode(',', sanitize_text_field($_POST['product_tags']))); wp_set_object_terms($post_id, $tags, 'product_tag'); } // 其他自定义元字段参照同样逻辑存储即可 // 示例:if (isset($_POST['your_custom_meta_key'])) update_post_meta($post_id, 'your_custom_meta_key', sanitize对应方法处理后的值); }, 20);
可选简化方案
如果不想手动写字段HTML和保存逻辑,可以直接在ACF中创建和WooCommerce原生字段meta_key同名的字段,比如创建数字类型字段,字段名设为_regular_price,ACF就会自动渲染表单、自动保存对应数据,不需要额外编写钩子。注意WooCommerce的价格类字段meta_key是以下划线开头的,创建ACF字段时不要遗漏前缀。
如果需要添加库存、运费、重量这类其他原生商品字段,只要找到对应的meta_key或者分类法名称,按照上述逻辑添加字段、编写保存逻辑即可,不需要额外安装插件。
内容的提问来源于stack exchange,提问作者Hossein52hz

