Вывод рекомендуемых товаров через пользовательский цикл в WooCommerce на странице шаблона
Я хочу вывести 6 рекомендуемых товаров из моего магазина WooCommerce на шаблоне home-page.php. После некоторых исследований я обнаружил, что правильный способ сделать это — через пользовательский цикл (я не хочу использовать шорткоды, так как хочу добавить дополнительные классы для стилизации и т.д.). Я также выяснил, что ключ, который WooCommerce использует для рекомендуемых товаров — это '_featured'. Я собрал код ниже для отображения любых товаров, которые я выбрал в качестве рекомендуемых в моем магазине, но он не работает... Любая помощь приветствуется.
<?php
$args = array(
'post_type' => 'product', // Тип записи - товар
'stock' => 1, // Только товары в наличии
'showposts' => 6, // Количество товаров для вывода
'orderby' => 'date', // Сортировка по дате
'order' => 'DESC' , // Порядок сортировки - по убыванию
'meta_query' => array(
array(
'key' => '_featured', // Ключ метаполя "рекомендуемый"
'value' => 0,
'compare' => '>', // Сравнение: значение больше 0
'type' => 'numeric' // Тип значения - числовой
)
)
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>
<li>
<?php
if ( has_post_thumbnail( $loop->post->ID ) )
echo get_the_post_thumbnail( $loop->post->ID, 'shop_catalog' );
else
echo '<img src="' . woocommerce_placeholder_img_src() . '" alt="Заглушка" width="65px" height="115px" />';
?>
<h3><?php the_title(); ?></h3>
<?php
echo $product->get_price_html();
woocommerce_template_loop_add_to_cart( $loop->post, $product );
?>
</li>
<?php
endwhile;
wp_reset_query();
?>

Это изменилось в WooCommerce 3.0. Теперь используется не только meta_query, но и tax_query. Аргументы теперь выглядят так:
$meta_query = WC()->query->get_meta_query();
$tax_query = WC()->query->get_tax_query();
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
);
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'posts_per_page' => $atts['per_page'],
'orderby' => $atts['orderby'],
'order' => $atts['order'],
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
Смотрите woocommerce/includes/class-wc-shortcodes.php

Измените ваши аргументы следующим образом:
$meta_query = WC()->query->get_meta_query();
$meta_query[] = array(
'key' => '_featured',
'value' => 'yes'
);
$args = array(
'post_type' => 'product',
'stock' => 1,
'showposts' => 6,
'orderby' => 'date',
'order' => 'DESC',
'meta_query' => $meta_query
);
Если вы перейдете в wp-content/plugins/woocommerce/includes/class-wc-shortcodes.php (@595), вы можете увидеть, как это сделано для шорткодов WC.

Важно отметить, что '_featured' хранится не как числовое значение, а как строка 'yes' или 'no'. Все остальное в оригинальном вопросе должно работать, у меня сработало.

Цикл рекомендуемых товаров в WooCommerce 3
<ul class="products">
<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => 12,
'tax_query' => array(
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
),
),
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
} else {
echo __( 'Товары не найдены' );
}
wp_reset_postdata();
?>

Согласно Wiki WooCommerce:
Создание пользовательских WP_Queries или запросов к базе данных [для получения товаров] может привести к поломке вашего кода в будущих версиях WooCommerce, так как данные постепенно переносятся в специальные таблицы для повышения производительности.
WooCommerce рекомендует использовать wc_get_products()
или WC_Product_Query()
вместо WP_Query()
или get_posts()
.
Я написал статью с кодом, который использовал для достижения желаемого результата: https://cfxdesign.com/create-a-custom-woocommerce-product-loop-the-right-way/

извините, без просмотра написанного кода сложно понять вашу статью. Не могли бы вы включить пример кода?

@HOY плагин для встраивания кода был сломан; сейчас это исправлено, и вы можете увидеть код!

спасибо, в поисках решений я нашел вот этот вариант ниже. Я не уверен, чем он отличается от вашего, так как не смог тщательно проверить ваш, но он очень короткий и помог мне с пользовательским циклом товаров. https://www.kathyisawesome.com/woocommerce-modifying-product-query/

Я знаю, что это довольно старо, но я только что поделился альтернативным решением здесь, и думаю, что оно может помочь тем, кто наткнулся на эту тему.
Вместо использования meta_query
или tax_query
, вы также можете использовать wc_get_featured_product_ids():
$args = array(
'post_type' => 'product',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
'post__in' => wc_get_featured_product_ids(),
);
$query = new WP_Query( $args );
Надеюсь, это поможет!

Основано на: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query
Я бы попробовал:
вне цикла:
$args = array (
'limit' => 6,
'orderby' => 'title',
'order' => 'ASC',
'category' => $club_cat,
'stock_status' => 'instock',
'featured' => true,
);
$products = wc_get_products( $args );
в цикле:
$query = new WC_Product_Query( array(
'limit' => 6,
'orderby' => 'title',
'order' => 'ASC',
'category' => $club_cat,
'stock_status' => 'instock',
'featured' => true,
'return' => 'ids',
) );
$products = $query->get_products();

Люди должны начать использовать wc_get_products, так как WooCommerce заявил, что это стандартный способ получения товаров. У wc_get_products есть аргумент featured, который просто нужно установить в true. Ниже приведен простой пример кода.
<?php
// Отображение рекомендуемых товаров по категории. В данном случае это "shirts" (слаг категории).
$query_args = array(
'featured' => true,
'category' => array( 'shirts' ),
);
$products = wc_get_products( $query_args );
global $post;
$columns = wc_get_loop_prop( 'columns' );
?>
<div class="woocommerce columns-<?php echo esc_attr( $columns ); ?>">
<?php
woocommerce_product_loop_start();
foreach ($products as $product) {
$post = get_post($product->get_id());
setup_postdata($post);
wc_get_template_part('content', 'product');
}
wp_reset_postdata();
woocommerce_product_loop_end();
?>
</div>
Полный пост можно прочитать здесь: https://jameshwartlopez.com/plugin/get-featured-products-of-a-category/

Если вы посмотрите в базе данных в таблице wp_postmeta
, то увидите, что meta_key
будет _featured
, а meta_value
будет содержать значение yes
или no
. Поэтому вместо значений 0
или 1
используйте yes
или no
.
<?php
$q = new WP_Query([
'post_type' => 'product',
'stock' => 1,
'showposts' => 3,
'orderby' => 'date',
'order' => 'DESC',
'meta_query' => [
['key' => '_featured', 'value' => 'yes' ]
]
]);
if ( $q->have_posts() ) :
while ( $q->have_posts() ) : $q->the_post();
// отображение информации о товаре
endwhile; wp_reset_query();
endif;
?>

<ul class="products">
<?php
$args = array(
'post_type' => 'product', // Тип записи - товар
'posts_per_page' => 12, // Количество товаров на странице
'tax_query' => array(
array(
'taxonomy' => 'product_visibility', // Таксономия видимости товара
'field' => 'name', // Поле для фильтрации
'terms' => 'featured', // Показывать только рекомендуемые товары
),
),
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
echo '<p>'.get_the_title().'</p>'; // Вывод заголовка товара
endwhile;
} else {
echo __( 'Товары не найдены', 'woocommerce' ); // Сообщение, если товары не найдены
}
wp_reset_postdata(); // Сброс данных запроса
?>
</ul><!--/.products-->

Актуально на 2021 год - Вам следует использовать wc_get_products()
Также, пример кода от Jameshwart (выше) у меня не сработал, вот как я настроил postdata и использовал wc_get_template. Протестировано и работает.
$args = array(
'status' => 'publish',
'limit' => 20,
'paginate' => true, //должно быть true, чтобы получить ->total
'return' => 'ids',
);
$products = wc_get_products( $args );
if ($products->total >= 1):
woocommerce_product_loop_start();
foreach($products->products as $pid):
do_action( 'woocommerce_shop_loop' );
$product = get_post($pid);
setup_postdata($GLOBALS['post'] =& $product);
wc_get_template_part('content', 'product');
endforeach;
wp_reset_postdata();
woocommerce_product_loop_end();
endif; //если есть товары
