【问题标题】:Product variation WP_Query with a product category in Woocommerce产品变体 WP_Query 与 Woocommerce 中的产品类别
【发布时间】:2018-08-26 19:36:38
【问题描述】:

使用 Woocommerce,我正在尝试为产品类别为“Apple”的产品变体帖子类型创建一个 WP_Query。

$args = array(
    'product_cat'    => 'Apple',
    'post_type'      => array('product', 'product_variation'),
    'post_status'    => 'publish',
    'key'            => '_visibility',
    'value'          => 'visible',
    'posts_per_page' => 100,
    'taxonomy'       => 'pa_size',
    'meta_value'     => '39',
    'meta_query'     => array(
        array(
            'key'         => '_stock',
            'value'       => 0,
            'compare'     => '>'
        )
    )
);

但我不能让它在这个查询中工作。如果我删除'product_cat' => 'Apple',则查询有效。为什么?

【问题讨论】:

    标签: php woocommerce product custom-taxonomy variations


    【解决方案1】:

    WP_Query 关于 Woocommerce 产品有很多错误:

    • 对于产品类别产品属性,您最好通常使用tax_query
    • 对于产品可见性,自 Woocommerce 3 起,它由 product_visibility 'exclude-from-search''exclude-from-catalog' 术语的分类法处理。

    关于产品变体的重要说明:

    • 产品类别(或产品标签)不由产品变体处理,而是由父变量产品处理
    • 变体的产品属性作为发布元数据处理,meta_key 前面带有“attribute_”和met_value,即术语段
    • 产品变体中未处理产品可见性,因为它们未显示在存档页面中。
    • 它们不会显示在存档页面中(如前所述)。

    因此,当使用WP_Query 时,您不能同时查询“产品”帖子类型和“product_variation”帖子类型因为它们确实不同

    要使您的查询适用于“product_variation”帖子类型,您需要一个小实用函数来获取产品类别的父变量产品(或任何自定义分类作为产品标签......)

    // Utility function to get the parent variable product IDs for a any term of a taxonomy
    function get_variation_parent_ids_from_term( $term, $taxonomy, $type ){
        global $wpdb;
    
        return $wpdb->get_col( "
            SELECT DISTINCT p.ID
            FROM {$wpdb->prefix}posts as p
            INNER JOIN {$wpdb->prefix}posts as p2 ON p2.post_parent = p.ID
            INNER JOIN {$wpdb->prefix}term_relationships as tr ON p.ID = tr.object_id
            INNER JOIN {$wpdb->prefix}term_taxonomy as tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
            INNER JOIN {$wpdb->prefix}terms as t ON tt.term_id = t.term_id
            WHERE p.post_type = 'product'
            AND p.post_status = 'publish'
            AND p2.post_status = 'publish'
            AND tt.taxonomy = '$taxonomy'
            AND t.$type = '$term'
        " );
    }
    

    代码进入您的活动子主题(或活动主题)的 function.php 文件中。测试和工作。 下面的WP_Query 需要


    此处WP_Query 代码用于产品变体 (仅)与特定产品类别和特定变体属性值相关:

    // Settings
    $cat_name = 'Apple'; // Product category name
    $attr_taxonomy = 'pa_size'; // Product attribute
    $attribute_term_slugs = array('39'); // <== Need to be term SLUGs
    
    $query = new WP_Query( array(
        'post_type'       => 'product_variation',
        'post_status'     => 'publish',
        'posts_per_page'  => 100,
        'post_parent__in' => get_variation_parent_ids_from_term( $cat_name, 'product_cat', 'name' ), // Variations
        'meta_query'      => array(
            'relation'    => 'AND',
            array(
                'key'     => '_stock',
                'value'   => 0,
                'compare' => '>'
            ),
            array( 
                'key'     => 'attribute_'.$attr_taxonomy, // Product variation attribute
                'value'   => $attribute_term_slugs, // Term slugs only
                'compare' => 'IN',
            ),
        ),
    ) );
    
    // Display the queried products count
    echo '<p>Product count: ' . $query->post_count . '<p>';
    
    // Displaying raw output for posts
    print_pr($query->posts);
    

    经过测试并且有效。

    【讨论】:

    • @Geme 希望这个解释对大家有用……
    • 我一直在寻找一个多小时的答案,这确实是最好的。谢谢
    【解决方案2】:

    有一些方法可以做到这一点,您可以循环产品并检查产品是否为variable,如果为真,您可以添加另一个循环以包含变化,但如果您必须使用WP_Query出于任何原因,您可以使用posts_join 过滤器,当您使用tax_query 时,它将添加一个LEFT JOIN sql 语句,它将wp_posts 表中的ID 列与@987654330 中的术语关系object_id 列进行比较@table,语句如下:

    LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    

    我们需要在这里做的就是添加一个OR 语句,这将使查询也查找帖子父 ID,并制作如下语句:(在 Woocommerce 产品变体中有一个帖子父级,即产品本身)

    LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id OR wp_posts.post_parent = wp_term_relationships.object_id)
    

    长话短说,我们该怎么做?

    我们将使用posts_join 过滤器来执行此操作,但请记住,我们需要在触发 wp_query 后立即删除过滤器(您也可以创建一些唯一变量,并且只有在该变量存在时才更改 join 语句

    function dornaweb_include_parent_categories_join($joins, $wp_query) {
        /*
         * You can make a condition to make sure this code will only run on your intended query
         * Altough removing the filter after wp_query also do it
         */
        if ($wp_query->query['my_include_parent_posts_cat_variable']) {
            global $wpdb;
            $find = "{$wpdb->prefix}posts.ID = {$wpdb->prefix}term_relationships.object_id";
            $joins = str_replace($find, $find . " OR {$wpdb->prefix}posts.post_parent = {$wpdb->prefix}term_relationships.object_id", $joins);
        }
    
        return $joins;
    }
    
    add_filter( 'posts_join' , "dornaweb_include_parent_categories_join", 99, 2);
    
    $products_list = new \WP_Query([
        'post_type'         => ['product', 'product_variation'],
        'posts_per_page'    => 15,
        'paged'             => !empty($_GET['page']) ? absint($_GET['page']) : 1,
        'tax_query'         => [
            [
                'taxonomy'  => 'product_cat',
                'terms'     => [$category],
            ]
        ],
        'my_include_parent_posts_cat_variable' => true
    ]);
    
    remove_filter( 'posts_join' , "dornaweb_include_parent_categories_join", 99, 2);
    

    【讨论】:

      猜你喜欢
      • 2018-12-19
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 2019-01-23
      • 2016-03-20
      • 1970-01-01
      相关资源
      最近更新 更多