我将woocommerce
的商品信息类型扩展为名为“已过期”的自定义post_status
。
所需的行为是将产品发布到商店并在一段时间后将其设置为过期。
只有在商店中才能看到已发布的产品,但在post_status设置为过期后,产品的固定链接仍然有效,但显示的是不同的模板。
Woocommerce本身只显示产品(在商店和单一产品视图中)默认情况下使用“发布”post_status
,所以我最初的想法是简单地挂钩pre_get_posts
并添加'过期'到post_status
查询变种。
稍微补充的是对帖子,产品和页面使用相同的slug。
http://example.com/product-name
为了实现这一切,我提出了以下代码:
add_action(
'pre_get_posts',
'custom_pre_get_posts'
);
function custom_pre_get_posts($query) {
global $wpdb;
if( !is_admin() && $query->is_main_query() && $post_name = $query->get('name')) {
$result = $wpdb->get_row(
$wpdb->prepare(
'SELECT post_type, ID, post_status FROM '.$wpdb->posts.' WHERE post_name = %s LIMIT 1',
$post_name
)
);
if(!empty($result) && $result->post_type == 'product'){
$query->set('name', $post_name);
$query->set('product', $post_name);
$query->set('post_type', $result->post_type);
$query->set('post_status', $result->post_status);
}
}
}
只需手动检查是否存在具有给定名称的帖子以及它具有的post_status。之后,相应地设置查询变量。
并为过期产品添加自定义模板:
add_filter(
'template_include',
'custom_expired_templates',
99
);
function custom_expired_templates($template){
global $wp_query;
$status = $wp_query->get('post_status');
$type = $wp_query->get('post_type');
if($status === 'expired' && $type ==='product'){
$template = locate_template( array( 'woocommerce/expired-single-product.php' ) );
}
return $template;
}
woocommerce/expired-single-product.php
只是我主题目录中woocmmerce/single-product.php
的简单副本。
上面的代码有效...但是这样做似乎有点hacky,因为自定义模板显示但是wordpress发送404标题并且标题设置为'找不到页面'所以我基本上覆盖404模板。
副作用是不会加载woocommerce样式和脚本。我真的试图深入研究woocommerce的文档,但我无法隔离错误。
有关实现理想行为的正确方法的任何建议吗?
更新
通过添加
验证生成的SQL查询add_action('the_posts','test_sql_request');
function test_sql_request($posts){
echo $GLOBALS['wp_query']->request;
var_dump($posts);
return $posts;
}
过期的产品有SQL请求:
SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = 'expired-product' AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'expired')) ORDER BY wp_posts.post_date DESC
但它返回一个空数组。在phpmyadmin中运行确切的查询返回了正确的帖子。发布产品的查询看起来完全相同,除了post_status和name(selfexplainatory)...但返回数组中的正确帖子。
答案 0 :(得分:3)
好的,所以失败不在上面发布的代码中,而是在post_status
本身的注册中:
function my_custom_post_status(){
register_post_status( 'expired', array(
'label' => _x( 'expired', 'product' ),
'public' => false,
'exclude_from_search' => true,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Expired <span class="count">(%s)</span>', 'Expired <span class="count">(%s)</span>' ),
) );
}
add_action( 'init', 'my_custom_post_status' );
问题部分是
'public' => false
并且必须更改为
'public' => true
即使您查询ID,我也不知道public属性会影响查询。已过期的产品ID为103,而$post = new WP_Query('p=103');
不会返回单个帖子,其中$post = get_post(103);
会返回正确的帖子。
对于类似情况的人来说,这可能会阻止一些未来的头痛。