引言
在运营基于 WooCommerce 的电商网站时,深度定制化是提升管理效率与用户体验的关键。本文将介绍如何通过代码实现两个核心功能:一是为自定义订单状态添加批量操作功能,以便快速管理订单;二是在用户注册及“我的账户”页面添加自定义下拉字段,以收集更丰富的用户信息。
为自定义订单状态添加批量操作
WooCommerce 后台默认支持对核心订单状态(如处理中、已完成)进行批量更改。若要为自定义状态(例如“待发货”)添加批量操作选项,需通过钩子扩展功能。
实现代码
将以下代码添加到主题的 functions.php 文件或自定义功能插件中。
// 1. 注册批量操作选项
add_filter( 'bulk_actions-edit-shop_order', 'custom_register_bulk_action' );
function custom_register_bulk_action( $bulk_actions ) {
$bulk_actions['mark_awaiting_shipment'] = '标记为待发货';
return $bulk_actions;
}
// 2. 处理批量操作请求
add_action( 'admin_action_mark_awaiting_shipment', 'custom_bulk_process_status' );
function custom_bulk_process_status() {
if ( ! isset( $_REQUEST['post'] ) || ! is_array( $_REQUEST['post'] ) ) {
return;
}
foreach ( $_REQUEST['post'] as $order_id ) {
$order = wc_get_order( $order_id );
if ( $order ) {
$order->update_status( 'wc-awaiting-shipment', '批量操作更新状态', true );
}
}
$location = add_query_arg( array(
'post_type' => 'shop_order',
'marked_awaiting_shipment' => 1,
'changed' => count( $_REQUEST['post'] ),
'ids' => join( ',', $_REQUEST['post'] ),
'post_status' => 'all'
), 'edit.php' );
wp_redirect( admin_url( $location ) );
exit;
}
// 3. 显示操作成功通知
add_action( 'admin_notices', 'custom_bulk_action_admin_notice' );
function custom_bulk_action_admin_notice() {
global $pagenow, $typenow;
if ( $typenow == 'shop_order' && $pagenow == 'edit.php' && isset( $_REQUEST['marked_awaiting_shipment'] ) ) {
$count = intval( $_REQUEST['changed'] );
echo '<div class="updated"><p>已成功更新 ' . $count . ' 个订单的状态。</p></div>';
}
}
关键点解析
- 钩子匹配:
bulk_actions-edit-shop_order中的edit-shop_order是订单列表页面的屏幕 ID。 - 动作命名:
admin_action_mark_awaiting_shipment的后半部分必须与注册的数组键值(mark_awaiting_shipment)一致。 - 状态标识:
update_status()中使用的状态标识符(如wc-awaiting-shipment)必须是系统中已注册的有效状态。
在注册表单添加自定义下拉字段
为了收集用户属性(如客户类型),我们需要在注册表单中添加下拉选择框,并确保数据能正确保存与回显。
完整实现代码
以下代码演示了如何添加一个“客户类型”字段,涵盖前端显示、数据保存及后台/前端编辑回显。
// 1. 在注册表单添加下拉字段
add_action( 'woocommerce_register_form', 'add_extra_register_select_field' );
function add_extra_register_select_field() {
?>
<p class="form-row form-row-wide">
<label for="customer_type">客户类型 <span class="required">*</span></label>
<select id="customer_type" name="customer_type" required>
<option value="">请选择...</option>
<option value="individual">个人</option>
<option value="company">企业</option>
<option value="reseller">经销商</option>
</select>
</p>
<?php
}
// 2. 注册时保存字段值
add_action( 'woocommerce_created_customer', 'save_extra_register_fields' );
function save_extra_register_fields( $customer_id ) {
if ( isset( $_POST['customer_type'] ) ) {
update_user_meta( $customer_id, 'customer_type', sanitize_text_field( $_POST['customer_type'] ) );
}
}
// 3. 在后台用户编辑页显示字段
add_action( 'show_user_profile', 'show_extra_register_fields_admin' );
add_action( 'edit_user_profile', 'show_extra_register_fields_admin' );
function show_extra_register_fields_admin( $user ) {
$value = get_user_meta( $user->ID, 'customer_type', true );
?>
<h3>额外信息</h3>
<table class="form-table">
<tr>
<th><label for="customer_type">客户类型</label></th>
<td>
<select id="customer_type" name="customer_type">
<option value="">请选择...</option>
<option value="individual" <?php selected( $value, 'individual' ); ?>>个人</option>
<option value="company" <?php selected( $value, 'company' ); ?>>企业</option>
<option value="reseller" <?php selected( $value, 'reseller' ); ?>>经销商</option>
</select>
</td>
</tr>
</table>
<?php
}
// 4. 在前端“我的账户”编辑页面显示字段
add_action( 'woocommerce_edit_account_form', 'show_extra_register_fields_frontend' );
function show_extra_register_fields_frontend() {
$user_id = get_current_user_id();
$value = get_user_meta( $user_id, 'customer_type', true );
?>
<p class="form-row form-row-wide">
<label for="customer_type">客户类型 <span class="required">*</span></label>
<select id="customer_type" name="customer_type">
<option value="">请选择...</option>
<option value="individual" <?php selected( $value, 'individual' ); ?>>个人</option>
<option value="company" <?php selected( $value, 'company' ); ?>>企业</option>
<option value="reseller" <?php selected( $value, 'reseller' ); ?>>经销商</option>
</select>
</p>
<?php
}
// 5. 保存后台及前端编辑页面的更新
add_action( 'personal_options_update', 'save_extra_register_fields_admin' );
add_action( 'edit_user_profile_update', 'save_extra_register_fields_admin' );
add_action( 'woocommerce_save_account_details', 'save_extra_register_fields_admin' );
function save_extra_register_fields_admin( $customer_id ) {
if ( isset( $_POST['customer_type'] ) ) {
update_user_meta( $customer_id, 'customer_type', sanitize_text_field( $_POST['customer_type'] ) );
}
}
功能逻辑说明
- 前端注册: 利用
woocommerce_register_form钩子在标准表单下方插入 HTML。 - 数据存储: 使用
update_user_meta将数据存入wp_usermeta表,并进行安全清理。 - 多端回显: 分别挂载到后台和前端编辑页面的钩子,确保用户在任何地方都能看到和修改该字段。
- 数据同步: 保存逻辑挂载到对应的更新动作中,确保修改生效。
修改支付网关标题与描述
有时为了提升转化率或符合品牌调性,需要修改支付网关在前端显示的文字。例如,将“货到付款”改为更具描述性的文案。
// 修改支付网关标题
add_filter( 'woocommerce_gateway_title', 'custom_payment_gateway_title', 25, 2 );
function custom_payment_gateway_title( $title, $gateway_id ) {
if ( 'cod' === $gateway_id ) { // 'cod' 是货到付款的默认 ID
$title = '送货时现金或刷卡支付';
}
return $title;
}
// 修改支付网关描述
add_filter( 'woocommerce_gateway_description', 'custom_payment_gateway_description', 25, 2 );
function custom_payment_gateway_description( $description, $gateway_id ) {
if ( 'cod' === $gateway_id ) {
$description = '送货上门时支付,支持现金与移动支付。';
}
return $description;
}
总结与注意事项
- 代码存放: 建议将代码放入子主题的
functions.php或使用自定义插件,避免主题更新后代码丢失。 - 安全性: 所有用户输入(如
$_POST)必须经过清理(如sanitize_text_field),防止 XSS 攻击。 - 测试环境: 修改订单状态和支付逻辑涉及核心业务,务必在测试站点充分验证后再部署至生产环境。
- 扩展性: 上述代码为标准模板,可根据实际业务需求调整字段名称、选项值及逻辑判断。