PHP-woocommerce过期产品自定义post_status

我将woocommerce的产品发布类型扩展为具有名为“ expired”的自定义post_status.

期望的行为是将产品发布到商店并将其设置为在特定时间段后过期.

在商店中只能看到已发布的产品,但是在post_status设置为过期但显示其他模板之后,该产品的永久链接仍然可以使用.

Woocommerce本身默认情况下仅显示带有“发布” post_status的产品(在商店和单一产品视图中),因此我的最初想法是简单地挂接到pre_get_posts并将“ expired”添加到post_status查询变量中.

还有一点是对帖子,产品和页面使用相同的标记.

http://example.com/page-name

http://example.com/post-name

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的纯副本.

上面的代码可以工作…但是这样做似乎有点不明智,因为自定义模板可以显示,但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和名称(自我解释)外,发布产品的查询看起来相同,但是在数组中返回正确的帖子.

解决方法:

好的,所以失败不是在上面发布的代码中,而是在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

我不知道public属性会影响查询,即使您查询ID也是如此.过期产品的ID为103,$post = new WP_Query(‘p = 103’);不返回单个帖子,其中$post = get_post(103);确实返回正确的帖子.

也许这可以防止类似情况的人将来头痛.

上一篇:PHP-WooCommerce:标头中的迷你购物车似乎已缓存


下一篇:php-强制WooCommerce出售和运送到仅一个州