如何关联下拉框值与Post ID并更新对应ACF字段?
问题解决:WordPress自定义表单关联Post ID更新ACF字段
核心问题分析
你的代码核心问题是下拉框命名未与对应客户的Post ID绑定,导致表单提交后无法将选择的Yes/No值与具体客户文章关联;同时错误使用了acf/save_post钩子(该钩子仅在WordPress默认文章保存流程中触发),且缺少必要的安全验证逻辑。
解决方案步骤
1. 绑定下拉框与Post ID
将下拉框的name改为数组格式,直接把当前客户的Post ID作为数组键,提交后可直接通过ID匹配对应值:
<select class="show-up" name='show_up[<?php echo get_the_ID(); ?>]' > <option value='' disabled selected>---</option> <option value="yes" <?php selected(get_field('did_they_show_up', get_the_ID()), 'yes'); ?>>Yes</option> <option value="no" <?php selected(get_field('did_they_show_up', get_the_ID()), 'no'); ?>>No</option> </select>
额外添加selected()函数回显ACF字段已有值,提升用户体验。
2. 添加表单安全验证
在表单中加入WordPress nonce字段,防止CSRF攻击:
<form id="updates" method="post" action=""> <?php wp_nonce_field('update_show_up_status', 'show_up_nonce'); ?> <!-- 表格内容 --> </form>
3. 重构表单提交逻辑
移除无用的acf/save_post钩子,直接在表单提交时处理更新:
if( isset($_POST['submit']) && isset($_POST['show_up']) ) { // 验证权限与nonce if (!wp_verify_nonce($_POST['show_up_nonce'], 'update_show_up_status') || !current_user_can('edit_posts')) { wp_die('权限验证失败'); } // 循环更新每个客户的状态 foreach($_POST['show_up'] as $post_id => $value) { if(in_array($value, ['yes', 'no'])) { update_field('did_they_show_up', $value, $post_id); } } // 跳转避免重复提交 wp_redirect(get_permalink()); exit; }
4. 清理冗余代码
删除原代码中无用的$posts_id_num数组、my_acf_save_post函数及调试输出代码。
修改后的完整代码
<?php $pickUpDate = get_field('pick_up_date', 167); $query_args = array( 'post_type' => 'clients', 'post_status' => 'publish', 'order' => 'ASC', 'orderby' => 'meta_value', 'meta_query' => array ( array ( 'key' => 'date_of_last_pick_up', 'compare' => '=', 'value' => $pickUpDate, ), ), 'posts_per_page' => -1, // 替换过时的numberposts参数 ); $the_query = new WP_Query( $query_args ); // 表单提交处理逻辑 if( isset($_POST['submit']) && isset($_POST['show_up']) ) { if (!wp_verify_nonce($_POST['show_up_nonce'], 'update_show_up_status') || !current_user_can('edit_posts')) { wp_die('权限验证失败'); } foreach($_POST['show_up'] as $post_id => $value) { if(in_array($value, ['yes', 'no'])) { update_field('did_they_show_up', $value, $post_id); } } wp_redirect(get_permalink()); exit; } ?> <form id="updates" method="post" action=""> <?php wp_nonce_field('update_show_up_status', 'show_up_nonce'); ?> <table class="table table-striped"> <thead> <th scope="col">Row #</th> <th scope="col">Did they arrive</th> <th scope="col">Name</th> <th scope="col">Pick Up Date</th> <th scope="col">Adults</th> <th scope="col">Children</th> <th scope="col">Dogs</th> <th scope="col">Cats</th> </thead> <?php $row_num = 1; if ( $the_query->have_posts() ) { while ( $the_query->have_posts() ) { $the_query->the_post(); $post_id = get_the_ID(); ?> <tr> <td><?php echo $row_num++; ?></td> <td> <select class="show-up" name='show_up[<?php echo $post_id; ?>]' > <option value='' disabled selected>---</option> <option value="yes" <?php selected(get_field('did_they_show_up', $post_id), 'yes'); ?>>Yes</option> <option value="no" <?php selected(get_field('did_they_show_up', $post_id), 'no'); ?>>No</option> </select> </td> <td> <a href="<?php the_permalink(); ?>"> <?php the_title(); ?> </a> </td> <td> <?php $nextPickUp = get_field('date_of_last_pick_up'); if ( $nextPickUp ) { $date = DateTime::createFromFormat( 'Ymd', $nextPickUp ); echo $date->format('M j Y'); } else { echo '----'; } ?> </td> <td><?php the_field('adults') ?: '----'; ?></td> <td><?php the_field('children') ?: '----'; ?></td> <td><?php the_field('dogs') ?: '----'; ?></td> <td><?php the_field('cats') ?: '----'; ?></td> </tr> <?php } wp_reset_postdata(); } else { ?> <p>No posts found</p> <?php } ?> </table> <input type="submit" name="submit" class="btn btn-secondary" value="Update"> </form>
关键修改说明
- 下拉框
name用数组格式绑定Post ID,直接建立值与文章的关联 - 添加nonce验证和权限检查,符合WordPress安全规范
- 用
posts_per_page替代过时的numberposts参数 - 简化字段输出逻辑,使用
?:运算符减少冗余代码 - 表单提交后跳转回当前页面,避免重复提交问题
内容的提问来源于stack exchange,提问作者Kris Weaver
相关产品推荐
相关产品推荐

