新增 WooCommerce 商品編輯頁的 product_type_options 選項

需求是我要在上圖的地方多增加一個 checkbox:

本想用 JS 硬幹,但爬了一下原始碼發現有 product_type_options 這個勾點可以使用,寫法跟 WooCommerce Setting API 滿像的,一樣是用一個關聯陣列包含欄位 id、label、description 跟 default 預設值:

private static function get_product_type_options() {
	return apply_filters(
		'product_type_options',
		array(
			'virtual'      => array(
				'id'            => '_virtual',
				'wrapper_class' => 'show_if_simple',
				'label'         => __( 'Virtual', 'woocommerce' ),
				'description'   => __( 'Virtual products are intangible and are not shipped.', 'woocommerce' ),
				'default'       => 'no',
			),
			'downloadable' => array(
				'id'            => '_downloadable',
				'wrapper_class' => 'show_if_simple',
				'label'         => __( 'Downloadable', 'woocommerce' ),
				'description'   => __( 'Downloadable products give access to a file upon purchase.', 'woocommerce' ),
				'default'       => 'no',
			),
		)
	);
}

搞定介面後要處理資料寫入的部分,有 woocommerce_admin_process_product_object 這個勾點可以使用,看他的寫法是用 $product 物件的 set_props 方法來儲存,於是我就依樣畫葫蘆用 set_props 來寫入我自己的值,結果搞了老半天一直寫不進去,去爬了 set_props 的實作,發現到我新增的值是不能用它寫入的:

$errors = $product->set_props(
	array(
		'sku'                => isset( $_POST['_sku'] ) ? wc_clean( wp_unslash( $_POST['_sku'] ) ) : null,
		'purchase_note'      => isset( $_POST['_purchase_note'] ) ? wp_kses_post( wp_unslash( $_POST['_purchase_note'] ) ) : '',
		'downloadable'       => isset( $_POST['_downloadable'] ),
		'virtual'            => isset( $_POST['_virtual'] ),
		'featured'           => isset( $_POST['_featured'] ),
		'catalog_visibility' => isset( $_POST['_visibility'] ) ? wc_clean( wp_unslash( $_POST['_visibility'] ) ) : null,
		...
	)
);

public function set_props( $props, $context = 'set' ) {
	$errors = false;

	foreach ( $props as $prop => $value ) {
		try {
			/**
			 * Checks if the prop being set is allowed, and the value is not null.
			 */
			if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) {
				continue;
			}
			$setter = "set_$prop";

			if ( is_callable( array( $this, $setter ) ) ) {
				$this->{$setter}( $value );
			}
		} catch ( WC_Data_Exception $e ) {
			if ( ! $errors ) {
				$errors = new WP_Error();
			}
			$errors->add( $e->getErrorCode(), $e->getMessage() );
		}
	}

	return $errors && count( $errors->get_error_codes() ) ? $errors : true;
}

最後跑去翻 $prdouct 物件的其他方法,找到跟訂單物件一樣的 update_meta_data 才能正確寫入,雖然理論上也是可以使用 update_post_meta 來處理,而且 $product 物件目前還沒看到資料表要拆分出來的消息,但避免日後需要另外修改,就還是乖乖用 update_meta_data 來實作:

// 新增介面
add_filter( 'product_type_options', 'add_my_setting' );
function add_onepage_checkout_setting( $options ) {
	$options['my_type_option'] = array(
		'id'            => '_my_type_option',
		'wrapper_class' => '',
		'label'         => __( 'my_type_option', 'woocommerce' ),
		'description'   => __( 'my_type_option_desc', 'woocommerce' ),
		'default'       => 'no',
	);
	return $options;
}


// 儲存值
add_action( 'woocommerce_admin_process_product_object', 'save_product_type_setting' );
function save_product_type_setting( $product ) {
	$product->update_meta_data( 'my_type_option', ! empty( $_POST['_my_type_option'] ) ? 'yes' : 'no' );
}

目錄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

賴俊吾 / Oberon Lai
賴俊吾 / Oberon Lai

現為全職 WordPress 工程師,網站開發經歷 11 年,專攻前端工程與 WordPress 佈景主題、外掛客製化開發

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!

專注於分享 WordPress 開發、接案技巧、專案管理等自由工作者必備知識與心得

© 2024 想點創意科技有限公司

想點創意科技有限公司 | 統一編號 90516823
Designed by Hend Design | 隱私權政策

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!