我想你最终会得到这样的结果:
编码方式
如果你想把这个逻辑放在你的模板/插件中,正如你在问题中所说的那样,有相当多的编码。
您需要:
创建自定义帖子类型为卖家创建metabox-在metabox文档中称为“回调”,创建保存metabox中数据的逻辑,为产品创建metabox检索前端数据,我假设您已经完成了这项操作,但让我们注册自定义帖子类型product
和seller
此处手动:
产品(“产品”)
/**
* Post Type: Products.
*/
function se345571_register_cpt_product() {
$labels = array(
"name" => __( "Products", "mytheme_textdomain" ),
"singular_name" => __( "Product", "mytheme_textdomain" ),
);
$args = array(
"label" => __( "Products", "mytheme_textdomain" ),
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"delete_with_user" => false,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"has_archive" => false,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => array( "slug" => "product", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "editor", "thumbnail" ),
);
register_post_type( "product", $args );
}
add_action( \'init\', \'se345571_register_cpt_product\' );
卖方(“卖方”)
/**
* Post Type: Sellers.
*/
function se345571_register_cpt_seller() {
$labels = array(
"name" => __( "Sellers", "mytheme_textdomain" ),
"singular_name" => __( "Seller", "mytheme_textdomain" ),
);
$args = array(
"label" => __( "Sellers", "mytheme_textdomain" ),
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"delete_with_user" => false,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"has_archive" => false,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => array( "slug" => "seller", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "editor", "thumbnail" ),
);
register_post_type( "seller", $args );
}
add_action( \'init\', \'se345571_register_cpt_seller\' );
为产品创建元盒
/**
* Adds a box to "advanced" part on the Seller edit screen.
* - See the different screens defined in $screens array.
*/
function se345571_add_seller_meta_box() {
$screens = array( \'seller\' );
foreach ( $screens as $screen ) {
// https://codex.wordpress.org/Function_Reference/add_meta_box - add_meta_box(), see for further params
add_meta_box(
\'product_settings_box\', // HTML \'id\' attribute of the edit screen section
__( \'Product settings\', \'mytheme_textdomain\' ), // Title of the edit screen section, visible to user
\'se345571_product_settings_meta_box_callback\', // Function that prints out the HTML for the edit screen section.
$screen // Which writing screen (\'post\',\'page\',\'dashboard\',\'link\',\'attachment\',\'custom_post_type\',\'comment\')
);
}
}
add_action( \'add_meta_boxes\', \'se345571_add_seller_meta_box\' );
在这里您可以看到,添加了一个动作,该动作在
add_meta_boxes - 这意味着,当Wordpress构建用于书写屏幕的元框时,它将调用我们的自定义
se345571_add_seller_meta_box()
功能也一样。
为metabox创建内容
/**
* Prints the box content.
*
* @param WP_Post $post The object for the current post/page.
*/
function se345571_product_settings_meta_box_callback( $post, $box ) {
// Add a nonce field so we can check for it later.
wp_nonce_field( \'se345571_product_settings_meta_box_data\', \'se345571_product_settings_meta_box_nonce\' );
/*
* Use get_post_meta() to retrieve an existing value
* from the database and use the value for the form.
*/
$value = get_post_meta( $post->ID, \'_product_settings\', true );
if ($value) {
$product_settings = json_decode($value, true);
}
// Get available products so we can show them in select box
$args = [
\'post_type\' => \'product\',
\'numberposts\' => -1,
\'orderby\' => \'id\',
\'order\' => \'ASC\'
];
$products = new WP_Query($args);
// As you can see, i have 5 product fields, this can be just about any number
$max = 5;
?>
<table>
<?php for ($index = 0; $index < $max; $index++) : ?>
<tr>
<td>
<label for="product-<?php echo $index + 1 ?>-product"><?php _e( \'Product #\' . ($index + 1), \'mytheme_textdomain\' )?></label>
</td>
<td>
<?php $productindex = 0; ?>
<select name="product_settings[<?php echo $index ?>][product_id]" id="product-<?php echo ($index + 1) ?>-product">
<?php while($products->have_posts()) : $products->the_post(); $productindex++; ?>
<option value="<?php the_ID() ?>" <?php echo (isset($product_settings[$index][\'product_id\']) && (int)$product_settings[$index][\'product_id\'] === get_the_ID()) ? \'selected\' : \'\' ?>><?php the_title() ?></option>
<?php endwhile; ?>
</select>
</td>
<td>
<label for="product-<?php echo $index + 1 ?>-price"><?php _e( \'Price\', \'mytheme_textdomain\' )?></label>
</td>
<td>
<input
name="product_settings[<?php echo $index ?>][price]"
type="text"
class="components-text-control__input"
id="product-<?php echo ($index + 1) ?>-price"
value="<?php echo isset($product_settings[$index][\'price\']) ? $product_settings[$index][\'price\'] : \'\' ?>">
</td>
</tr>
<?php endfor; ?>
</table>
<?php
// Don\'t forget about this, otherwise you will mess up with other data on the page
wp_reset_postdata();
}
好的,这里有很多代码。正如该线程中的其他人所建议的,您可能会发现使用javascript(如select2.js)扩展此逻辑很有用。您可以将其直接写入此函数的HTML输出。
保存数据
/**
* When the post is saved, saves our custom data.
*
* @param int $post_id The ID of the post being saved.
*/
function se345571_product_settings_meta_box_data( $post_id, $post ) {
// Check if our nonce is set.
if ( ! isset( $_POST[\'se345571_product_settings_meta_box_nonce\'] ) ) {
return;
}
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[\'se345571_product_settings_meta_box_nonce\'], \'se345571_product_settings_meta_box_data\' ) ) {
return;
}
// If this is an autosave, our form has not been submitted, so we don\'t want to do anything.
if ( defined( \'DOING_AUTOSAVE\' ) && DOING_AUTOSAVE ) {
return;
}
/* OK, it\'s safe for us to save the data now. */
// Make sure that it is set.
if ( ! isset( $_POST[\'product_settings\'] ) ) {
return;
}
// HERE STARTS THE ACTUAL FUNCTIONALITY
// Sanitize user input.
$product_settings = json_encode( $_POST[\'product_settings\'] );
// Update the meta field in the database.
update_post_meta( $post_id, \'_product_settings\', $product_settings );
}
add_action( \'save_post\', \'se345571_product_settings_meta_box_data\', 10, 2 );
这是另一个钩子,save\\u post和我们的自定义逻辑。基本上是1:1
Codex 对于add\\u meta\\u box()函数,只需交换POST字段名称。
为产品创建元数据库
您要求显示卖家为不同产品输入的价格,因为这里没有任何前端,我将在产品管理页面中显示。但同样的逻辑也可以用于在前端显示它。
/**
* Adds a box to "advanced" part on the Seller edit screen.
* - See the different screens defined in $screens array.
*/
function se345571_add_product_meta_box() {
$screens = array( \'product\' );
foreach ( $screens as $screen ) {
// https://codex.wordpress.org/Function_Reference/add_meta_box - add_meta_box(), see for further params
add_meta_box(
\'product_settings_box\', // HTML \'id\' attribute of the edit screen section
__( \'Seller prices\', \'mytheme_textdomain\' ), // Title of the edit screen section, visible to user
\'se345571_seller_prices_meta_box_callback\', // Function that prints out the HTML for the edit screen section.
$screen // Which writing screen (\'post\',\'page\',\'dashboard\',\'link\',\'attachment\',\'custom_post_type\',\'comment\')
);
}
}
add_action( \'add_meta_boxes\', \'se345571_add_product_meta_box\' );
/**
* Prints the box content.
*
* @param WP_Post $post The object for the current post/page.
*/
function se345571_seller_prices_meta_box_callback( $post, $box ) {
$product_id = get_the_ID();
$args = [
\'post_type\' => \'seller\',
\'numberposts\' => -1,
\'meta_query\' => [
[
\'key\' => \'_product_settings\',
\'value\' => \'"product_id":"\' .$product_id. \'"\',
\'compare\' => \'LIKE\',
]
]
];
$sellers = new WP_Query($args);
while($sellers->have_posts()) : $sellers->the_post();
$seller_prices = json_decode(get_post_meta( get_the_ID(), \'_product_settings\', true ), true);
$seller_prices_for_product = array_filter($seller_prices, function($element) use ($product_id) {
if (isset($element[\'product_id\'])) {
return (int)$element[\'product_id\'] === $product_id;
}
return false;
});
foreach($seller_prices_for_product as $price) :
?>
<p>
<?php the_title(); ?> <?php _e(\'for\', \'mytheme_textdomain\'); ?> <?php echo $price[\'price\'] ?>
</p>
<?php
endforeach;
endwhile;
// Don\'t forget about this, otherwise you will mess up with other data on the page
wp_reset_postdata();
}
检索数据
最后,当您需要在前端获取数据时,您可以转到模板并使用类似以下内容:
$value = get_post_meta( get_the_ID(), \'_product_settings\', true );
$product_settings = json_decode($value, true);
get_post_meta() 使用您当前的帖子ID、要检索的字段的键(可选)以及只需要一个或所有元的任何内容(可选-未设置返回所有自定义字段)。
也就是说,我实际上会选择插件方式(除非你自己编写插件)。
像其他人指出的那样,对于这种情况,我会选择插件方式Advanced Custom Fields 插件。基本上可以做相同的事情,上面的代码。
通过用户界面设置元框。
检索数据
要检索数据,您可以使用函数get\\u field()或the\\u field()-无论您想立即返回值还是打印值(与WP中的命名约定相同)。
get_field(\'your_field_name\');
来源和进一步阅读
http://themefoundation.com/wordpress-meta-boxes-guide/https://codex.wordpress.org/Function_Reference/add_meta_boxhttp://www.smashingmagazine.com/2011/10/04/create-custom-post-meta-boxes-wordpress/