Учимся создавать разные шаблоны товаров для разных категорий. Данная технология пригодится в оформлении принципиально разных по подаче товаров. Также на основе этого можно создавать посадочные страницы категорий, создавая им любое оформление.
Структура шаблонов woocommerce
Я использую вот такую иерархию шаблонов woocommerce (уже немного отличающуюся от той которую использовал ранее)
<?php if ( is_product() ) : ?>
Шаблон товара
<?php elseif ( is_shop() ) : ?>
<?php if ( is_search() ) : ?>
Шаблон поиска
<?php else: ?>
Шаблон каталога товаров (витрина)
<?php endif; ?>
<?php else: ?>
Шаблон категории товара
<?php endif; ?>
Там где выводится шаблон категории товара прописываем условия вывода.
<?php $product_cat = get_queried_object();
if($product_cat->slug == 'elektronika'): ?>
Здесь будет верстка лэндинга!
<?php get_template_part( 'woocommerce/taxonomy-product_cat-elektronika' ); ?>
<?php else: ?>
<h1 id="title"><?php printf( __( '%s', 'twentythirteen' ), single_cat_title( '', false ) ); ?></h1>
<div class="box">
<?php get_sidebar(); ?>
<div class="block-9" id="content">
<?php the_widget( 'WC_Widget_Layered_Nav_Filters' ); ?>
<?php get_template_part( 'woocommerce/archive-product' ); //woocommerce_content(); ?>
</div>
</div>
<?php endif; ?>
Можно не прописывать конструкцию
$product_cat = get_queried_object();
if($product_cat->slug == 'elektronika'):
А вместо нее использовать простое условие
if ( is_product_category( 'elektronika' ) ) :
Для прописанной категорий товара (в данном примере — Электроника) будет выводится другой шаблон. Данный способ неудобен тем, что необходимо вручную прописывать условия. А если у нас будет много категорий с подкатегориями? В этом случае целесообразно задать таксономии новый параметр Шаблон в глобальную переменную term (по аналогии как это делает плагин taxonomy term image master).
Вывод разных шаблонов товаров в категории
Еще один уровень кастомизации категории WC это разные варианты вывода самих товаров. В этом случае мы должны по определенному запросу разделять визуализацию товаров. Если в простом варианте, то для определенных категорий выводить товары без цены. Если делать более продвинутый вариант — товары могут выводить вовсе по разному.
Если в назначении шаблона woocommerce использовать универсальную функцию woocommerce_content(); то почему то игнорируется шаблон archive-product.php. А для разделения вывода товаров в категории нужен именно archive-product.php.
get_template_part( ‘woocommerce/content-single-product’ ); — вывод карточки товара
get_template_part( ‘woocommerce/archive-product’ ); — вывод категории товара
get_template_part( ‘product-cat-list’ ); — разработанный мной шаблон вывода каталога товаров
woocommerce_content(); — вывод результатов поиска по товарам
В файле archive-product.php (внутри цикла while) нам нужно добавить условия вывода товаров и создать соответствующий файл в папке woocommerce/content-laminat.php
<?php $product_cat = get_queried_object();
if($product_cat->term_id == 24): ?>
<?php wc_get_template_part( 'content', 'laminat' ); ?>
<?php else: ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endif; ?>
Создаем атрибут Шаблон у категории
Ранее мы пришли к выводу, что было бы удобнее создать в категориях параметр — Шаблон, в зависимости от которого будут выводится разные шаблоны категорий. Так вот, я переделал плагин taxonomy term image master, создав новый плагин wc-template-select:
if ( ! defined( 'ABSPATH' ) ) { exit; }
if ( ! class_exists( 'Taxonomy_Term_Template' ) ) :
class Taxonomy_Term_Template {
// array of slugs for the taxonomies we are targeting
// api: use filter 'taxonomy-term-template-taxonomy' to override
private $taxonomies = array( 'category' );
// defined during __construct() for i18n reasons
// api: use filter 'taxonomy-term-template-labels' to override
private $labels = array();
// @deprecated: option_name for pre-term-meta data storage
// api: use filter 'taxonomy-term-template-option-name' to override
private $option_name = '';
// our term meta key
// api: use filter 'taxonomy-term-template-meta-key' to override
private $term_meta_key = 'term_template';
// Simple singleton to enforce one instance
// @return Taxonomy_Term_Template object
static function instance() {
static $object = null;
if ( is_null( $object ) ) {
$object = new Taxonomy_Term_Template();
}
return $object;
}
private function __clone(){} // prevent cloning
private function __wakeup(){} // prevent unserialization
// Init the plugin and hook into WordPress
private function __construct() {
// default labels
$this->labels = array(
'fieldTitle' => __( 'Шаблон' ),
'fieldDescription' => __( 'Выберите шаблон, для этого элемента' ),
'adminColumnTitle' => __( 'Шаблон' ),
);
// allow overriding of the html text
$this->labels = apply_filters( 'taxonomy-term-template-labels', $this->labels );
// allow overriding of the target taxonomies
$this->taxonomies = apply_filters( 'taxonomy-term-template-taxonomy', $this->taxonomies );
if ( ! is_array( $this->taxonomies ) ) {
$this->taxonomies = array( $this->taxonomies );
}
// @deprecated: allow overriding of option_name
// default option name keyed to the taxonomy
$this->option_name = $this->taxonomies[0] . '_term_templates';
$this->option_name = apply_filters( 'taxonomy-term-template-option-name', $this->option_name );
// allow overriding of term_meta
$this->term_meta_key = apply_filters( 'taxonomy-term-template-meta-key', $this->term_meta_key );
// hook into WordPress
$this->hook_up();
}
// Hook into WordPress
private function hook_up(){
// зарегистрируйте наш термин meta
register_meta( 'term', $this->term_meta_key, array(
'type' => 'string',
'description' => 'Шаблон термина',
'single' => true,
'sanitize_callback' => null,
'auth_callback' => null,
'show_in_rest' => false,
) );
// добавьте наши данные, когда срок будет восстановлен
add_filter( 'get_term', array( $this, 'get_term' ) );
add_filter( 'get_terms', array( $this, 'get_terms' ) );
add_filter( 'get_object_terms', array( $this, 'get_terms' ) );
// нужно только добавить большинство хуков в админке
if ( is_admin() ) {
foreach ( $this->taxonomies as $taxonomy ) {
// добавить поле Шаблон в формы таксономии
add_action( $taxonomy . '_add_form_fields', array( $this, 'taxonomy_add_form' ) );
add_action( $taxonomy . '_edit_form_fields', array( $this, 'taxonomy_edit_form' ) );
// hook into term administration actions
add_action( 'create_' . $taxonomy, array( $this, 'taxonomy_term_form_save' ) );
add_action( 'edit_' . $taxonomy, array( $this, 'taxonomy_term_form_save' ) );
// custom admin taxonomy term list columns
add_filter( 'manage_edit-' . $taxonomy . '_columns', array( $this, 'taxonomy_term_column_template' ) );
add_filter( 'manage_' . $taxonomy . '_custom_column', array( $this, 'taxonomy_term_column_template_content' ), 10, 3 );
}
}
}
// Добавить новый столбец, который показывают выбранный шаблон.
// @param $columns
// @return mixed
function taxonomy_term_column_template( $columns ){
$columns['term_template'] = $this->labels['adminColumnTitle'];
return $columns;
}
// Показывать выбранное изображение термина во вновь созданном столбце администратора
// @param $content
// @param $column_name
// @param $term_id
// @return mixed
function taxonomy_term_column_template_content( $content, $column_name, $term_id ){
if ( 'term_template' == $column_name ){
$term = get_term( $term_id );
if ( $term->term_template ) {
$content = get_term_meta( $term_id, $this->term_meta_key, true );
}
}
return $content;
}
// Добавьте данные изображения к любому соответствующему вызову get_term (). Двойная функция как вспомогательная функция для этого -> get_terms ().
// @param $_term
// @return object
function get_term( $_term ) {
// только модифицируйте термин, когда имеете дело с нашими таксономиями
if ( is_object( $_term ) && in_array( $_term->taxonomy, $this->taxonomies ) ) {
// default to null if not found
$template_id = get_term_meta( $_term->term_id, $this->term_meta_key, true );
$_term->term_template = !empty( $template_id ) ? $template_id : null;
}
return $_term;
}
// Добавьте term_template данные в объекты, когда вызывается get_terms () или wp_get_object_terms ().
// @param $terms
// @return array
function get_terms( $terms ) {
foreach( $terms as $i => $term ){
if ( is_object( $term ) && !empty( $term->taxonomy ) ) {
$terms[ $i ] = $this->get_term( $term );
}
}
return $terms;
}
// HTML формы для термина таксономии
// @param int $image_ID the image ID
// @return string the html output for the image form
function taxonomy_term_template_field($term) {
wp_nonce_field( 'taxonomy-term-template-form-save', 'taxonomy-term-template-save-form-nonce' );
$params = array(
'table' => 'Таблица',
'landing' => 'Лэндинг',
);
?>
<select id="taxonomy-term-template-id" name="taxonomy_term_template">
<option value="">По умолчанию</option>';
<?php foreach( $params as $val => $name ): ?>
<option value="<?php echo $val; ?>" <?php echo selected( $term, $val, 0 ); ?>><?php echo $name; ?></option>';
<?php endforeach; ?>
</select>
<p class="description"><?php echo $this->labels['fieldDescription']; ?></p>
<?php
}
// Добавить поле при создании нового термина таксономии
function taxonomy_add_form($term){
?>
<div class="form-field term-image-wrap">
<label><?php echo $this->labels['fieldTitle']; ?></label>
<?php $this->taxonomy_term_template_field($term); ?>
</div>
<?php
}
// Добавить поле при редактировании терминов таксономии
// @param $term | object | the term object
function taxonomy_edit_form( $term ){
// ensure we have our term_template data
if ( !isset( $term->term_template ) ){
$term = $this->get_term( $term, $term->taxonomy );
}
?>
<tr class="form-field">
<th scope="row" valign="top"><label><?php echo $this->labels['fieldTitle']; ?></label></th>
<td class="taxonomy-term-template-row">
<?php $this->taxonomy_term_template_field( $term->term_template ); ?>
</td>
</tr>
<?php
}
// Функция сохраняющая мета термина таксономии
// @param $term_id
function taxonomy_term_form_save( $term_id ) {
// наши требования к сохранению:
if (
// nonce был представлен и проверен
isset( $_POST['taxonomy-term-template-save-form-nonce'] ) &&
wp_verify_nonce( $_POST['taxonomy-term-template-save-form-nonce'], 'taxonomy-term-template-form-save' ) &&
// данные о таксономии и данные taxonomy_term_template
isset( $_POST['taxonomy'] ) &&
isset( $_POST['taxonomy_term_template'] ) &&
// представленная таксономия является одной из таксономий, с которыми мы имеем дело
in_array( $_POST['taxonomy'], $this->taxonomies )
)
{
// получить term_meta и назначить ему old_template
$old_template = get_term_meta( $term_id, $this->term_meta_key, true );
// sanitize the data and save it as the new_template
$new_template = $_POST['taxonomy_term_template'];
// if an image was removed, delete the meta data
if ( $old_template && '' === $new_template ) {
delete_term_meta( $term_id, $this->term_meta_key );
}
// if the new image is not the same as the old update the term_meta
else if ( $old_template !== $new_template ) {
update_term_meta( $term_id, $this->term_meta_key, $new_template );
}
}
}
}
endif;
// Инициализируйте плагин, вызывая его экземпляр в WordPress action 'init'
function taxonomy_term_template_init() {
Taxonomy_Term_Template::instance();
}
add_action( 'init', 'taxonomy_term_template_init' );
// Использовать для различных таксономий
function the_term_template_taxonomy( $taxonomy ) {
return array( 'product_cat', 'product_tag', 'category', 'brend' );
}
add_filter( 'taxonomy-term-template-taxonomy', 'the_term_template_taxonomy' );
Одной из основных «фишек» плагина является то, что параметр term_template доступен из переменной WP_Term Object:
$product_cat = get_queried_object();
print_r($product_cat);
Результат:
WP_Term Object ( [term_id] => 107 [name] => Электроника [slug] => elektronika [term_group] => 0 [term_taxonomy_id] => 107 [taxonomy] => product_cat [description] => [parent] => 0 [count] => 1 [filter] => raw [term_template] => landing )
Далее прописываем условия по выводу шаблонов
<?php $product_cat = get_queried_object();
if ( $product_cat->term_template == 'landing' ) : ?>
Шаблон лэндинга
<?php elseif ($product_cat->term_template == 'table'): ?>
Шаблон таблицы
<?php else: ?>
Шаблон по умолчанию
<?php endif; ?>
Было бы здорово доработать проверку наличия шаблона у родительской категории, при отсутствии шаблона у текущей категории, но это уже излишне. По крайней мере назначить шаблон подкатегориям, причем сделать это можно при их создании, легче чем прописывать сами категории в условиях вывода.
Выводить или нет категории
Добавим еще один выбор, на этот раз включение категории в выводе каталога:
// Включить термин в вывод каталога на главной
if ( ! class_exists( 'Taxonomy_Term_Enable' ) ) :
class Taxonomy_Term_Enable {
// array of slugs for the taxonomies we are targeting
// api: use filter 'taxonomy-term-enable-taxonomy' to override
private $taxonomies = array( 'category' );
// defined during __construct() for i18n reasons
// api: use filter 'taxonomy-term-enable-labels' to override
private $labels = array();
// @deprecated: option_name for pre-term-meta data storage
// api: use filter 'taxonomy-term-enable-option-name' to override
private $option_name = '';
// our term meta key
// api: use filter 'taxonomy-term-enable-meta-key' to override
private $term_meta_key = 'term_enable';
// Simple singleton to enforce one instance
// @return Taxonomy_Term_Enable object
static function instance() {
static $object = null;
if ( is_null( $object ) ) {
$object = new Taxonomy_Term_Enable();
}
return $object;
}
private function __clone(){} // prevent cloning
private function __wakeup(){} // prevent unserialization
// Init the plugin and hook into WordPress
private function __construct() {
// default labels
$this->labels = array(
'fieldTitle' => __( 'Включить категорию в категории' ),
'fieldDescription' => __( 'Выводить ли данную категорию в каталоге на главной странице' ),
'adminColumnTitle' => __( 'Включен в каталог' ),
);
// allow overriding of the html text
$this->labels = apply_filters( 'taxonomy-term-enable-labels', $this->labels );
// allow overriding of the target taxonomies
$this->taxonomies = apply_filters( 'taxonomy-term-enable-taxonomy', $this->taxonomies );
if ( ! is_array( $this->taxonomies ) ) {
$this->taxonomies = array( $this->taxonomies );
}
// @deprecated: allow overriding of option_name
// default option name keyed to the taxonomy
$this->option_name = $this->taxonomies[0] . '_term_enables';
$this->option_name = apply_filters( 'taxonomy-term-enable-option-name', $this->option_name );
// allow overriding of term_meta
$this->term_meta_key = apply_filters( 'taxonomy-term-enable-meta-key', $this->term_meta_key );
// hook into WordPress
$this->hook_up();
}
// Hook into WordPress
private function hook_up(){
// зарегистрируйте наш термин meta
register_meta( 'term', $this->term_meta_key, array(
'type' => 'string',
'description' => 'Включение термина в каталог',
'single' => true,
'sanitize_callback' => null,
'auth_callback' => null,
'show_in_rest' => false,
) );
// добавьте наши данные, когда срок будет восстановлен
add_filter( 'get_term', array( $this, 'get_term' ) );
add_filter( 'get_terms', array( $this, 'get_terms' ) );
add_filter( 'get_object_terms', array( $this, 'get_terms' ) );
// нужно только добавить большинство хуков в админке
if ( is_admin() ) {
foreach ( $this->taxonomies as $taxonomy ) {
// добавить поле Шаблон в формы таксономии
add_action( $taxonomy . '_add_form_fields', array( $this, 'taxonomy_add_form' ) );
add_action( $taxonomy . '_edit_form_fields', array( $this, 'taxonomy_edit_form' ) );
// hook into term administration actions
add_action( 'create_' . $taxonomy, array( $this, 'taxonomy_term_form_save' ) );
add_action( 'edit_' . $taxonomy, array( $this, 'taxonomy_term_form_save' ) );
// custom admin taxonomy term list columns
add_filter( 'manage_edit-' . $taxonomy . '_columns', array( $this, 'taxonomy_term_column_enable' ) );
add_filter( 'manage_' . $taxonomy . '_custom_column', array( $this, 'taxonomy_term_column_enable_content' ), 10, 3 );
}
}
}
// Добавить новый столбец, который показывают выбранный шаблон.
// @param $columns
// @return mixed
function taxonomy_term_column_enable( $columns ){
$columns['term_enable'] = $this->labels['adminColumnTitle'];
return $columns;
}
// Показывать выбранное изображение термина во вновь созданном столбце администратора
// @param $content
// @param $column_name
// @param $term_id
// @return mixed
function taxonomy_term_column_enable_content( $content, $column_name, $term_id ){
if ( 'term_enable' == $column_name ){
$term = get_term( $term_id );
if ( $term->term_enable ) {
$content = get_term_meta( $term_id, $this->term_meta_key, true );
}
}
return $content;
}
// Добавьте данные изображения к любому соответствующему вызову get_term (). Двойная функция как вспомогательная функция для этого -> get_terms ().
// @param $_term
// @return object
function get_term( $_term ) {
// только модифицируйте термин, когда имеете дело с нашими таксономиями
if ( is_object( $_term ) && in_array( $_term->taxonomy, $this->taxonomies ) ) {
// default to null if not found
$enable_id = get_term_meta( $_term->term_id, $this->term_meta_key, true );
$_term->term_enable = !empty( $enable_id ) ? $enable_id : null;
}
return $_term;
}
// Добавьте term_enable данные в объекты, когда вызывается get_terms () или wp_get_object_terms ().
// @param $terms
// @return array
function get_terms( $terms ) {
foreach( $terms as $i => $term ){
if ( is_object( $term ) && !empty( $term->taxonomy ) ) {
$terms[ $i ] = $this->get_term( $term );
}
}
return $terms;
}
// HTML формы для термина таксономии
// @param int $image_ID the image ID
// @return string the html output for the image form
function taxonomy_term_enable_field($term) {
wp_nonce_field( 'taxonomy-term-enable-form-save', 'taxonomy-term-enable-save-form-nonce' );
?>
<label><input id="taxonomy-term-enable-id" type="checkbox" name="taxonomy_term_enable"
<?php echo checked( $term, 'yes', 0 ); ?>><?php echo $this->labels['fieldDescription']; ?></label>
<?php
}
// Добавить поле при создании нового термина таксономии
function taxonomy_add_form($term){
?>
<div class="form-field term-image-wrap">
<label><?php echo $this->labels['fieldTitle']; ?></label>
<?php $this->taxonomy_term_enable_field($term); ?>
</div>
<?php
}
// Добавить поле при редактировании терминов таксономии
// @param $term | object | the term object
function taxonomy_edit_form( $term ){
// ensure we have our term_enable data
if ( !isset( $term->term_enable ) ){
$term = $this->get_term( $term, $term->taxonomy );
}
?>
<tr class="form-field">
<th scope="row" valign="top"><label><?php echo $this->labels['fieldTitle']; ?></label></th>
<td class="taxonomy-term-enable-row">
<?php $this->taxonomy_term_enable_field( $term->term_enable ); ?>
</td>
</tr>
<?php
}
// Функция сохраняющая мета термина таксономии
// @param $term_id
function taxonomy_term_form_save( $term_id ) {
// наши требования к сохранению:
if (
// nonce был представлен и проверен
isset( $_POST['taxonomy-term-enable-save-form-nonce'] ) &&
wp_verify_nonce( $_POST['taxonomy-term-enable-save-form-nonce'], 'taxonomy-term-enable-form-save' ) &&
// данные о таксономии и данные taxonomy_term_enable
isset( $_POST['taxonomy'] ) &&
isset( $_POST['taxonomy_term_enable'] ) &&
// представленная таксономия является одной из таксономий, с которыми мы имеем дело
in_array( $_POST['taxonomy'], $this->taxonomies )
) {
update_term_meta( $term_id, 'term_enable', 'yes' );
} else {
delete_term_meta( $term_id, 'term_enable' );
}
}
}
endif;
// Инициализируйте плагин, вызывая его экземпляр в WordPress action 'init'
function taxonomy_term_enable_init() {
Taxonomy_Term_Enable::instance();
}
add_action( 'init', 'taxonomy_term_enable_init' );
// Использовать для различных таксономий
function the_term_enable_taxonomy( $taxonomy ) {
return array( 'product_cat', 'product_tag', 'category' );
}
add_filter( 'taxonomy-term-enable-taxonomy', 'the_term_enable_taxonomy' );
Вывод каталога в этом случае будет выглядеть следующим образом:
<div class="grid">
<div class="grid-sizer"></div>
<?php $terms = get_terms( array(
'taxonomy' => 'product_cat',
'hide_empty' => true,
'pad_counts'=> true,
'orderby' => 'name',
'order' => 'DESC',
'meta_key' => 'term_enable'
//'parent' => 0 // только категории верхнего уровня
) ); ?>
<?php if($terms) : ?>
<?php foreach($terms as $term) : ?>
<div class="grid-item <?php echo $term->term_template; ?>">
<a href="<?php echo get_term_link($term->term_id); ?>">
<p><?php echo $term->name;?></p>
<?php $thumbnail_id = get_term_meta( $term->term_id, 'thumbnail_id', true );
$image = wp_get_attachment_url( $thumbnail_id );
if (!empty($image)) {
echo '<img src="'.$image.'" title="'.$term->name.'" alt="'.$term->name.'"
srcset="'.wp_get_attachment_image_srcset( $thumbnail_id, 'large' ).'" sizes="'.wp_get_attachment_image_sizes( $thumbnail_id, 'large' ).'">';
} else {
echo '<img src="/wp-content/uploads/2021/06/beige-bgd.png" title="'.$term->name.'" alt="'.$term->name.'">';
}?>
</a>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
В этом выводе также применена технология плиточного вывода.
[site-socialshare]
Добрый день.
Я устроился на работу и мне дали доделать сайт интернет-магазина.
Там чудо разработчик каким-то образом умудрился вывести продукты из категории товаров в файле page.php, вместо taxonomy-product_cat.
Не подскажете, как он смог переопределить этот файл.
Добрый день! Надо видеть код. Я предполагаю, что он мог создать и назначить странице шаблон и в нем уже делать все что угодно.
Скажите, а как переопределить не для одной категории, а сразу для несольких вот тут
<?php $product_cat = get_queried_object();
if($product_cat->term_id == 24): ?>
Вам поможет функция php in_array. Логика примерно такая:
$os = array('24','25','27');
$product_cat = get_queried_object();
if (in_array($product_cat->term_id, $os)) {
//функция
}
-тся, -ться.
Спасибо!