如何为简单产品和可变产品添加自定义字段
在本教程中,您将学习如何为产品创建自定义字段并在您的商店中显示它。我们将一起设置插件的基本结构,并了解 WordPress 的命名约定和 WooCommerce 的钩子机制。最终,您将获得一个用于添加自定义字段的可用插件。
完整的插件代码 是基于 WordPress 6.2 和 WooCommerce 7.6.0 编写的。
前置条件
要完成本教程,您需要安装 WordPress,并激活 WooCommerce 插件。您还需要至少设置一个 简单产品,或者您可以 导入 WooCommerce 的示例产品。
设置插件
首先,让我们执行 创建插件的基本结构 的步骤。
首先,导航到您的 wp-content/plugins 文件夹,然后运行:
npx @wordpress/create-block -t @woocommerce/create-woo-extension woo-product-fields
然后,我们导航到新的文件夹并运行安装和构建命令:
cd woo-product-fields
npm install # 安装依赖
npm run build # 构建 JavaScript
WordPress 具有自己的类文件命名约定,该约定默认情况下不符合 PSR-4 标准。要了解更多关于命名约定的信息,请参阅 WP Handbook。我们将使用标准的 "class-my-classname.php" 格式,因此,让我们修改 composer.json 文件中的 autoload 配置为:
"autoload": {
"classmap": ["includes/", "includes/admin/"]
},
保存后,运行 dump-autoload 命令以生成类映射,在终端中运行:
composer dump-autoload -o
这将生成一个新的 vendor/composer/autoload_classmap.php 文件,其中包含 /includes/ 和 /includes/admin/ 文件夹中所有类的列表。每当我们添加、删除或移动类文件时,都需要重复此命令。
WooCommerce 钩子
我们的目标是为 WooCommerce 产品创建一个新的自定义文本字段,用于保存新的库存信息,以便在商店中显示。为此,我们需要修改 WooCommerce 后台管理区域中包含库存信息的区域。
WooCommerce 允许我们通过 钩子 将我们的代码添加到这些区域,钩子是 WordPress 扩展代码的标准方法。在 "库存" 部分,我们有以下可用的操作钩子:
对于我们的 WooCommerce 扩展,我们将使用 woocommerce_product_options_inventory_product_data 钩子,将我们的字段附加到该部分的末尾。
创建我们的类
让我们开始创建一个新的类,该类将包含字段的代码。 在 /includes/admin/ 文件夹中添加一个名为 class-product-fields.php 的新文件。 在类中,我们添加命名空间、如果有人尝试直接调用该文件则中止,以及一个 __construct 方法,该方法调用 hooks() 方法:
<?php
namespace WooProductField\Admin;
defined( 'ABSPATH' ) || exit;
class ProductFields {
public function __construct() {
$this->hooks();
}
private function hooks() {}
}
然后,在终端中运行 composer dump-autoload -o 命令以重新生成类映射。 完成后,我们将该类添加到 setup.php 的 __construct() 函数中,如下所示:
class Setup {
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ) );
new ProductFields();
}
}
添加自定义字段
在配置类并调用其方法后,我们可以创建一个函数来添加自定义字段。WooCommerce 提供了自己的 woocommerce_wp_text_input( $args ) 函数,我们可以在此处使用它。$args 是一个数组,允许我们设置文本输入的数据,我们将使用全局 $product_object 对象来访问存储的元数据。
public function add_field() {
global $product_object;
?>
<div class="inventory_new_stock_information options_group show_if_simple show_if_variable">
<?php woocommerce_wp_text_input(
array(
'id' => '_new_stock_information',
'label' => __( 'New Stock', 'woo_product_field' ),
'description' => __( 'Information shown in store', 'woo_product_field' ),
'desc_tip' => true,
'value' => $product_object->get_meta( '_new_stock_information' )
)
); ?>
</div>
<?php
}
让我们看一下数组中的参数。ID 将用作数据库中的 meta_key。标签和描述显示在数据部分,通过将 desc_tip 设置为 true,它将显示为悬停在信息图标上时的提示。最后一个参数 value 确保如果已经存储了值,则会显示该值。
对于 div 类,类名 show_if_simple 和 show_if_variable 将控制何时显示我们的部分。这与 JavaScript 代码相关联,该代码动态地隐藏/显示部分。例如,如果我们希望从可变产品中隐藏该部分,我们可以简单地删除 show_if_variable。
现在我们有了该字段,我们需要保存它。为此,我们可以钩入 woocommerce_process_product_meta,它接受两个参数:$post_id 和 $post:
public function save_field( $post_id, $post ) {
if ( isset( $_POST['_new_stock_information'] ) ) {
$product = wc_get_product( intval( $post_id ) );
$product->update_meta_data( '_new_stock_information', sanitize_text_field( $_POST['_new_stock_information'] ) );
$product->save_meta_data();
}
}
此函数检查我们的新字段是否在 POST 数组中。如果存在,我们创建产品对象,更新我们的元数据并保存元数据。update_meta_data 函数将更新现有的元字段或添加新的元字段。由于我们正在向数据库插入数据,因此我们必须 清理我们的字段值。
为了使所有内容正常工作,我们添加以下钩子:
private function hooks() {
add_action( 'woocommerce_product_options_inventory_product_data', array( $this, 'add_field' ) );
add_action( 'woocommerce_process_product_meta', array( $this, 'save_field' ), 10, 2 );
}
现在,如果我们在产品屏幕上进行刷新,我们可以看到我们的新字段。
如果添加数据并保存产品,则新的元数据将插入到数据库中。
添加自定义字段到产品
此时,您已经拥有了一个可以保存产品自定义字段为产品元数据的插件。
在商店中显示字段
如果要在商店中显示新的字段,可以使用 WooCommerce 产品类的 get_meta() 方法:$product->get_meta( '_new_stock_information' )
让我们开始创建一个新的文件 /includes/class-product.php。您可能已经注意到,该文件位于 /admin/ 文件夹之外,因为此代码将在前端运行。因此,在设置类时,我们也会相应地调整命名空间:
<?php
namespace WooProductField;
defined( 'ABSPATH' ) || exit;
class Product {
public function __construct() {
$this->hooks();
}
private function hooks() { }
}
再次运行 composer dump-autoload -o 以更新我们的类映射。
如果您查看了插件的设置,您可能会注意到 /admin/setup.php 仅在 WordPress 后台运行时才会被调用。因此,为了调用我们的新类,我们将在 /woo-product-field.php 中直接添加它:
public function __construct() {
if ( is_admin() ) {
new Setup();
}
new WooProductField\Product();
}
对于将字段添加到前端,我们有几种选项。我们可以创建一个主题模板,但如果我们在使用与 WooCommerce 兼容的主题,并且不需要进行任何其他更改,那么一种快速的方法是使用钩子。如果我们查看 /woocommerce/includes/wc-template-hooks.php,我们可以看到所有现有的 woocommerce_single_product_summary 动作,该动作控制产品页面的顶部部分:
对于我们的插件,我们将在摘要之后添加新的库存信息,并使用 21 作为优先级:
private function hooks() {
add_action( 'woocommerce_single_product_summary', array( $this, 'add_stock_info' ), 21 );
}
在我们的函数中,我们使用 适当的转义函数 输出库存信息,在这种情况下,我建议使用 esc_html() 来强制使用纯文本。
public function add_stock_info() {
global $product;
?>
<p><?php echo esc_html( $product->get_meta( '_new_stock_information' ) ); ?> </p>
<?php
}
现在,如果刷新产品页面,我们的库存信息将显示在摘要下方:
太棒了!您已完成本教程,并且拥有一个可以添加新自定义字段并在商店中显示它的 WooCommerce 插件!🎉 我希望它向您展示了如何通过钩子轻松扩展 WooCommerce,并根据您或您的客户的商店需求进行定制!
以下是一个可选的任务,如果您对可变产品感兴趣。您可以稍后再回来查看。
如何处理可变产品?
上面的示例是使用一个简单产品进行的。但是,如果存在变体,例如一件有多种尺码的 T 恤,并且我们希望为每个变体存储不同的库存信息,该怎么办?WooCommerce 允许我们使用 可变产品类型 来实现这一点。
可变产品类型具有变体作为其子项。要为变体添加自定义字段,我们可以使用 woocommerce_variation_options_inventory 钩子,并使用 woocommerce_save_product_variation 进行保存。因此,让我们更新我们的 hooks() 方法,添加新的动作钩子,如下所示:
private function hooks() {
add_action( 'woocommerce_product_options_inventory_product_data', array( $this, 'add_field' ) );
add_action( 'woocommerce_process_product_meta', array( $this, 'save_field' ), 10, 2 );
add_action( 'woocommerce_variation_options_inventory', array( $this, 'add_variation_field' ), 10, 3 );
add_action( 'woocommerce_save_product_variation', array( $this, 'save_variation_field' ), 10, 2 );
}
配置方式与简单产品非常相似,主要区别在于我们需要使用 $loop ID,该 ID 用于区分不同的变体,并且我们将使用 wrapper_class 将其显示为全宽的文本输入框:
public function add_variation_field( $loop, $variation_data, $variation ) {
$variation_product = wc_get_product( $variation->ID );
woocommerce_wp_text_input(
array(
'id' => '_new_stock_information' . '[' . $loop . ']',
'label' => __( 'New Stock Information', 'woo_product_field' ),
'wrapper_class' => 'form-row form-row-full',
'value' => $variation_product->get_meta( '_new_stock_information' )
)
);
}
用于保存的代码如下:
public function save_variation_field( $variation_id, $i ) {
if ( isset( $_POST['_new_stock_information'][$i] ) ) {
$variation_product = wc_get_product( $variation_id );
$variation_product->update_meta_data( '_new_stock_information', sanitize_text_field( $_POST['_new_stock_information'][$i] ) );
$variation_product->save_meta_data();
}
}
现在,我们有一个新的变体字段,用于存储新的库存信息。 如果您看不到新的字段,请确保为该变体启用“管理库存”,方法是在变体详情中选中复选框。
在前端商店显示变体的方式对于可变产品来说略有不同,因为只有当客户进行选择时,网页上的某些内容才会更新。 这超出了本教程的范围,但如果您感兴趣,可以查看 /woocommerce/assets/js/frontend/add-to-cart-variation.js,了解 WooCommerce 的实现方式。
如何查找钩子?
每个人都有自己偏好的方法,但对我来说,最快的方法是在 WooCommerce 插件的代码中查找。每个数据部分的 code 可以在 /woocommerce/includes/admin/meta-boxes/views 目录下找到。要查看如何处理 库存 部分,请查看 html-product-data-inventory.php 文件,而要查看 变体 的处理方式,请查看 html-variation-admin.php 文件。