Day21 - 铁人付外挂设定介面(三)- 自订栏位

先来回顾一下目前铁人付金流外挂的资料夹结构:

iron-pay
├── composer.json
├── composer.lock
├── iron-pay.php
├── src
│   └── Options.php
└── vendor

上一篇我们完成了 WooCommerce 的全域设定,接下来我们要在後台的订单管理页新增一个交易结果以及纪录金流商的回传讯息,以便客户日後可以针对有问题的订单进行追踪。WordPress 的後台有很多现成的栏位,参考下图:

如果要新增的很容易,使用函式 add_meta_box() 跟勾点 add_meta_boxes 来传入产生表单栏位的 HTML,最後使用勾点 save_post 在储存文章时触发 update_post_meta() 即可将该栏位的资讯写入资料库:

<?php
function irp_add_custom_box() {
	$screens = array( 'shop_order' );
	foreach ( $screens as $screen ) {
		add_meta_box(
			'iron_pay_result',
			'铁人付交易结果',
			'irp_custom_box_html',
			$screen,
			'side',
			'low'
		);
	}
}
add_action( 'add_meta_boxes', 'irp_add_custom_box' );

function irp_custom_box_html( $post ) {
	$code   = get_post_meta( $post->ID, '_irp_resp_code', true );
	$result = get_post_meta( $post->ID, '_irp_resp_result', true );
	?>
	<p>回传代号<input type="text" name="irp_resp_code" value="<?php echo esc_attr( $code ); ?>" x-readonly style="display:block;width:100%;margin-top: 5px;"></p>
	<p>交易结果<textarea rows="5" name="irp_resp_result" x-readonly style="display:block;width:100%;margin-top: 5px;"><?php echo esc_textarea( $result ); ?></textarea></p>
	<?php
}

function irp_save_postdata( $post_id ) {
	if ( array_key_exists( 'irp_resp_code', $_POST ) ) {
		update_post_meta(
			$post_id,
			'_irp_resp_code',
			$_POST['irp_resp_code']
		);
	}
	if ( array_key_exists( 'irp_resp_result', $_POST ) ) {
		update_post_meta(
			$post_id,
			'_irp_resp_result',
			$_POST['irp_resp_result']
		);
	}
}
add_action( 'save_post', 'irp_save_postdata' );

这样就完成我们要的栏位了~

以上范例修改自官方文件,然而这个做法真的要记起来每个步骤真的非常困难,再加上还必须要知道一堆函式与勾点,我写了这麽多年,每次真的要用到时都还是要去查文件,觉得效率不高,因此我整理了一套 wp-metabox 的 PHP 套件来简化这些步骤,接下来示范如何使用这个套件来完成一样的自订栏位。

新增订单资料夹结构

我们先进入 src,资料夹,并新增 Posts 以及在 Posts 里面的 ShopOrder 资料夹,并增加 Metabox.php 档案,完成後资料夹结构如下:

iron-pay
├── composer.json
├── composer.lock
├── iron-pay.php
├── src
│   ├── Options.php
│   └── Posts
│       └── ShopOrder
│           └── Metabox.php
└── vendor

之所以要用两个资料夹来分类,主要目的是为了方便日後管理,我是根据 WordPress 的资料库结构来设计的,Posts 资料夹对应的是 wp_posts,而 ShopOrder 是 post type 为 shop_order 的相关档案,里面放了自订栏位的 Metabox.php,如果之後需要做订单相关的非同步处理,就可以增加 Ajax.php,或是要做订单资料的捞取就可以新增 Query.php。

万一之後客户需要在商品管理页面增加自订栏位,那它的档案路径就会是 Posts/Product/Metabox.php,因为 Product 也是存放在 wp_posts 里面的。这样的分类方式可能要对资料表有一定的熟悉程度会比较好上手,这样做的好处是如果在其他专案也需要用到订单的自订栏位或是其他功能,整包资料夹复制过去後修改命名空间的第一层名称就可以重用。

namespace {yourprefix}/Posts/ShopOrder

然後类别名称、档案名称都不用再修改,不然常见的 WordPress 外挂档名写法都是要带一堆前缀,然後宣告类别前要先检查类别是否存在,引入命名空间之後可以很大程度增加程序码的重用性,同时让资料夹结构对应到命名空间,就不用再取 class-yourprefix-shop-order-metabox.php 这种又臭又长的名字。

安装 wp-metabox 套件

将目录切回到 iron-pay 资料夹底下,来进行 wp-metabox 套件的安装:

 ~/Sites/woocommerce/wp-content/plugins/iron-pay$ composer require oberonlai/wp-metabox 

安装完成後开启 src/Posts/ShopOrder/Metabox.php 档案,贴入以下程序码:

<?php

namespace Irp\Posts\ShopOrder;

use ODS\Metabox;

$metabox = new Metabox(
	array(
		'id'       => 'iron_pay_field',
		'title'    => '铁人付交易结果',
		'screen'   => 'shop_order',
		'context'  => 'side',
		'priority' => 'low',
	)
);

$metabox->addText(
	array(
		'id'    => 'irp_resp_code',
		'label' => '回应代号',
	)
);

$metabox->addTextarea(
	array(
		'id'    => 'irp_resp_result',
		'label' => '交易结果',
	)
);

结果如下:

有别於最原始的范例,我们再也不用记一堆韩式跟勾点,也不用处理栏位值得储存或更新,只要建立 Metabox 实例,然後看要新增什麽栏位就用对应的方法,透过跟 WooCommerce Settings API 类似的阵列值传入方式来设定栏位,以下针对 Metabox 类别传入的参数做说明:

id 自订区块的唯一 ID,所有的自订栏位都要放在自订区块中,如果想要新增不同的区块则需要再建立另外一个 new Metabox()

title 自订栏位的显示名称

screen 设定显示在哪个 Post Type 底下,我们要显示在订单页所以是 shop_order。该如何知道目标的页面是哪种 post type? 可以从网址最後的一个参数 post_type 就知道:

https://woocommerce.test/wp-admin/edit.php?post_type=shop_order

context 自订区块的显示位置,可选值有 normal, side, advanced,side 是在右侧栏

priority 自订区块与其他区块的顺序,可选值有 high、core、default、low,越高越前面

此外,该套件支援八种自订栏位,常见的文字、单选框、下拉选单,另外还有图片上传、所见即所得编辑器以及重复器,具体的用法都很相似,传入的参数都只有三个,id、label 与 desc,比较特别的是重复器栏位,但在这个外挂之中我们先不会用到它,更多栏位用法可以参考套件中的 README.md。

另外如果我们需要传入更多的参数像是 class、style、attr 之类的属性也非常容易,只要开启 vendor/oberonlai/wp-metabox/Metabox.php 这个类别,就能看到 add 栏位以及产出 HTML 的方法,从中我们还可以学到 WordPress 的过滤方法,像是 esc_attr() 以及 esc_html() 等等,这些都是在开发外挂时需要注意的安全性。

眼尖的朋友可能会发现 WooCommerce 有内建一个订单备注的栏位,在实务上我们常常也会用它来记录订单的状态变更以及相关资讯,但如果一个订单备注过多时就会变得不太好找,所以我自己在习惯上都还是会另外开一个自订区块来处理金流商的回传资讯。

完成设定页面後下一篇我们先来了解 WooCommerce 的结帐流程,以及最重要的金流类别 WC_Payment_Gateway。

本文同步发表於:https://oberonlai.blog/tw/woocommerce-payment-metabox/


<<:  WordPress 显示最後更新日期的 3 种方法 (外挂、程序码、Post Meta Data) – 提高 SEO 排名

>>:  Day 7 从个资隐私裁罚案例中学习

Day 03:不用三分钟,建立第一个 Angular 专案范本

接下来,我们就要来建立第一个专案范本。 首先,我们可以在桌面上先建一个资料夹,命名叫 Angular...

Varying - fragment shader 之资料

大家好,我是西瓜,你现在看到的是 2021 iThome 铁人赛『如何在网页中绘制 3D 场景?从 ...

那些被忽略但很好用的 Web API / Battery

低电量~低~低~电量~ 吕士轩-低电量 今天要分享的也是一个使用情境偏少的 API,但如果你有想要...

并行程序的潜在问题 (一)

建立 Thread 的成本远低於 Process 的成本,执行 Context switch 时的效...

[想试试看JavaScript ] 浏览器里的 Javascript

在网页里会碰到的 Javascript 语法,大约分成三个部分 Javascript (以 ECMA...