Простая витрина товаров на WordPress

Когда для сайта нужно сделать некоторое подобие товаров, для которых в будущем не нужна будет корзина, сортировка по параметрам и прочие атрибуты полноценного онлайн магазина - можно прибегнуть к плагину ACF, создать категорию товаров и назначить дополнительные "товарные" поля ко всем постам этой категории. Единственный недостаток - это получающаяся мешанина постов (статейные посты, новостные, товарные посты). Для наведения порядка самым очевидным решением будет добавить новый тип записи и вынести такие посты в отдельный пункт меню. В вордпресс есть специальный класс который создаёт пользовательские таксономии (об этом очень подробно расписал товарищ Kama), но проще воспользоваться плагином - Custom Post Type UI.
Вообще витрина товаров это просто пример того, что можно сделать на плагине Custom Post Type UI + ACF. Главная функция плагина распределять данные и наводить порядок, сами разработчики в примерах создают на основе этого плагина коллекцию фильмов, но вы можете практически какие угодно данные вложить в функционал этого плагина. По моему опыту самые востребованные вещи на WP + Custom Post Type UI это:
- Витрины или даже онлайн магазины;
- Аренда квартир или офисов;
- Прокат оборудования.
Выделенные в отдельное меню товары можно также распределять по категориям, для этого понадобится создать таксономию, в которую поместить новый тип товаров созданных ранее в меню "Add New Post Type". Но начнём по порядку, для начала стоит хотя бы бегло ознакомиться с доступными настройками и опциями плагина Custom Post Type.
Основные настройки плагина Custom Post Type UI
Создание произвольного типа записи
Обязательными для заполнения являются три пункта
Post Type Slug
Идентификатор вашего нового типа поста.
Plural Label
Имя, во множественном числе, которое будет отображаться в системе (например в меню) при взаимодействии с этим типом поста.
Singular Label
Тоже что и выше только в единственном числе.
Список настроек интерфейса в созданных типах поста
Настройки заменяют надписи в меню, на странице списка постов и при редактировании поста.
Название | Описание | По умолчанию |
Post Type Description | Добавьте описание | |
Menu Name | Имя для пункта меню | Значение из поля |
All Items | Подпункт меню, открывает список постов | |
Add New | Заменяет надпись "Добавить новую" в подпункте меню и на странице редактирования | Добавить новую |
Add New Item | Заменяет надпись "Добавить запись" на странице добавления поста | Добавить запись |
Edit Item | Заменяет надпись "Редактировать запись" на странице редактирование поста | Редактировать запись |
New Item | Добавить | |
View Item | Изменить название ссылки ведущей на просмотр поста при его редактировании | Просмотреть запись |
Search Item | Меняет надпись на кнопки поиска | Поиск записей |
Not Found | Надпись которая появляется в случае если не найдены записи | Записей не найдено. |
Not Found in Trash | Надпись которая появляется в случае если не найдены записи в корзине | Записей в корзине не найдено. |
Parent | Заменяет надпись | |
Featured Image | Заменяет стандартные надписи в блоке добавления изображения, а также во всплывающем окне добавления изображения | Изображение записи |
Set Featured Image | Установить изображение записи | |
Remove Featured Image | Удалить изображение записи | |
Use Featured Image | Использовать изображение записи | |
Archives | Архив | |
Insert into item | Заменяет текст в кнопке "Вставить в запись" при вставки картинки в медиаменеджере | Вставить в запись |
Uploaded to this Item | Заменяет текст в кнопке "Загрузить" | Загрузить |
Filter Items List | Заменяет текст в кнопке фильтр в списке постов | Фильтр |
Items List Navigation | ? | ? |
Items List | Заменяет текст "Список постов" | Все записи |
Attributes | Заменяет текст в блоке Атрибуты при редактировании поста | Атрибуты |
Список настроек Custom Post Type UI
Menu Position
Стандартное значение: 5.
Описание: Указывает каким по счету пунктом будет идти меню кастомных постов. Указывается от 5, т.к. первыми идут стандартные пункты меню.
Menu Icon
Стандартное значение: пусто (но тем не менее по умолчанию выводиться иконка канцелярской кнопки).
Описание: Для того чтобы добавить иконку вы можете вставить либо её непосредственный урл, либо класс Dashicons. Выбрав из списка Dashicons, нужную иконку кликнете по ней, она отобразится слева сверху с полным названием класса. Скопировав класс и вставив его в поле "Menu Icon" иконка появится рядом с вашим кастомным пунктом в меню.
Вывод кастомных постов в шаблоне
Для примера создадим тип поста Product. После установки плагина , в меню добавится пункт CPT UI, в котором можно создавать новые типы постов и категории. Итак создаём свой тип поста Product, идем в CPT UI -> Add New Post Type и заполняем основные поля:
Обратите внимание на поле "Supports" в настройках (в расшифровки выше есть описание назначения полей), стоит добавить "excerpt" для включения поддержки коротких описаний для этого кастомного типа поста.
Теперь добавим возможность раскладывать по категориям такие посты. Переходим в CPT UI -> Add/Edit Taxonomies заполняем основные поля и выбираем только что созданный тип поста в поле "Attach to Post Type":
Для добавления постов переходим в появившемся меню с названием вашего типа постов. Если вы не изменяли настройки интерфейса при создании типа поста, то создание постов в новой таксономии не будет отличаться от обычных действий. Создадим несколько категорий и товаров, а потом свяжем их друг с другом:
Для того чтобы увидеть посты с новой таксономией (помимо добавления самих постов) нужно вывести ссылки на сайте. Это можно сделать через меню добавив в него кастомные категории. Перейдя в меню, проверьте чтобы в настройка экрана был включен вывод кастомной категории:
Добавив вывод постов категорий в меню, можно будет перейти в кастомную категорию на сайте:
Дополнительные свойства для товаров с помощью плагина Advanced Custom Fields
Получившийся "магазин" на последнем скриншоте несколько не дотягивает даже до витрины товаров. Как минимум у товара должно быть несколько свойств, которые по хорошему нужно вывести непосредственно в категории где отображен список товаров. Дальнейшие действия будут связаны с созданием небольшого кода для кастомной таксономии и несколько стилей для чуть более гармоничного отображения, так что если вы не хотите писать цену в поле с описанием товара, то придётся немного покодить.
Для начала создадим несколько доп полей в плагине Advanced Custom Fields, пусть это будет две цены - Стандартная и Акционная.
Привязываем эти поля к нашему кастомному типу поста "product" в поле Rules. После чего переходим в сам товар и заполняем/дозаполняем его.
Редактирование шаблона c Custom Post Type UI и Advanced Custom Fields
Для того чтобы отредактировать файлы шаблона для начало надо создать дочернюю тему (если вы не используете свой шаблон). В теме необходимо создать два файла:
- "taxonomy.php" - файл отвечает за вывод списка товаров;
- "content-product.php" - файл отвечает за вывод внутренностей товарного блока, должен лежать в папке "template-parts"
- "single-product.php" - файл отвечает за вывод конкретного поста (продукта);
- "functions.php" - функции в этом файле будут добавлены в родительский файл "functions.php", нам в дочерней теме он понадобиться для парочки модификаций.
Для того чтобы показать как редактировать шаблон я буду редактировать стандартную WordPress тему - "twentysixteen", соответственно дочерняя тема должна называться "twentysixteen-child". Для тех кто не хочет читать дальше можно просто посмотреть получившийся код на моём github.
Style.css дочерней темы является главным, WP даже не грузит родительский style.css, поэтому в нашем случае мы его просто импортируем. Добавим в CSS вывод в три колонки, небольшую стилизацию информации в товарном блоке, а также стили для будущей всплывающей формы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/* Theme Name: Twenty Sixteen Theme URI: https://wordpress.org/themes/twentysixteen/ Template: twentysixteen Author: the WordPress team and Atlogex Author URI: https://atlogex.com/ Author URI: https://wordpress.org/ Description: Twenty Sixteen is a modernized take on an ever-popular WordPress layout — the horizontal masthead with an optional right sidebar that works perfectly for blogs and websites. It has custom color options with beautiful default color schemes, a harmonious fluid grid using a mobile-first approach, and impeccable polish in every detail. Twenty Sixteen will make your WordPress look beautiful everywhere. Version: 0.1 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Tags: one-column, two-columns, right-sidebar, accessibility-ready, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-images, flexible-header, microformats, post-formats, rtl-language-support, sticky-post, threaded-comments, translation-ready, blog Text Domain: twentysixteen This theme, like WordPress, is licensed under the GPL. Use it to make something cool, have fun, and share what you've learned with others. */ @import url("../twentysixteen/style.css"); .site-header { padding: 0 4.5455%; } .tax-product_category article.product { width: 32%; margin: 0.48%; display: inline-block; vertical-align: top; margin-bottom: 2.0em; } .tax-product_category article.product .post-thumbnail { margin-bottom: 0.625em; } body.tax-product_category article.product .entry-content { width: 100%; height: 80px; text-align: center; float: left; font-size: 0.8em; } .tax-product_category article.product .entry-title { font-size: 1.5rem; text-align: center; } .entry-price { height: 40px; text-align: center; } .ep-standart { margin: auto; } span.ep-price { font-size: 0.8em; color: #ad0b0b; text-decoration: line-through; } span.ep-pricesale { margin: auto; font-weight: bold; color: #179c35; } .btn-order { background: #1a1a1a; border: 0; border-radius: 2px; color: #fff; font-family: Montserrat, "Helvetica Neue", sans-serif; font-weight: 700; letter-spacing: 0.046875em; line-height: 1; padding: 0.84375em 0.875em 0.78125em; text-transform: uppercase; transition: 300ms; overflow: hidden; width: 70%; text-align: center; margin: 0 auto; cursor: pointer; } .btn-order:hover { background: #007acc; transition: 300ms; } .cf-buyitnow { display: none; position: fixed; width: 400px; left: 50%; margin-left: -200px; padding: 5% 2% 0; top: 15%; text-align: center; font-weight: bold; color: rgba(255, 255, 255, 0.74); border-radius: 5px; background: rgba(0, 0, 0, 0.9); box-shadow: 0px 0px 40px rgb(0, 0, 0); z-index: 100; } .cf-buyitnow input[type="text"], .cf-buyitnow input[type="email"], .cf-buyitnow input[type="tel"], .cf-buyitnow input[type="number"], .cf-buyitnow textarea { background: #f7f7f7; background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 0)); border: 1px solid #d1d1d1; border-radius: 2px; color: #686868; padding: 6px 4px; width: 100%; } .cf-buyitnow input[type="submit"] { background: rgba(255, 0, 0, 0.72); } .cf-buyitnow p { margin: 0 0 1em; } .cf-product-url { display: none; } .cf-close { position: absolute; right: 10px; top: 10px; filter: brightness(10); cursor: pointer; } .cf-custominfo { text-align: center; color: #fff; margin-bottom: 10px; } |
Для вывода списка товаров создадим и отредактируем файл "taxonomy.php":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?php /** * The template for displaying archive pages * * Used to display archive-type pages if nothing more specific matches a query. * For example, puts together date-based pages if no date.php file exists. * * If you'd like to further customize these archive views, you may create a * new template file for each one. For example, tag.php (Tag archives), * category.php (Category archives), author.php (Author archives), etc. * * @link https://codex.wordpress.org/Template_Hierarchy * * @package WordPress * @subpackage Twenty_Sixteen * @since Twenty Sixteen 1.0 */ get_header(); ?> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <?php the_archive_title( '<h1 class="page-title">', '</h1>' ); the_archive_description( '<div class="taxonomy-description">', '</div>' ); ?> </header><!-- .page-header --> <?php // Start the Loop. while ( have_posts() ) : the_post(); /* * Include the Post-Format-specific template for the content. * If you want to override this in a child theme, then include a file * called content-___.php (where ___ is the Post Format name) and that will be used instead. */ get_template_part( 'template-parts/content-product', get_post_format() ); // End the loop. endwhile; // Previous/next page navigation. the_posts_pagination( array( 'prev_text' => __( 'Previous page', 'twentysixteen' ), 'next_text' => __( 'Next page', 'twentysixteen' ), 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>', ) ); // If no content, include the "No posts found" template. else : get_template_part( 'template-parts/content', 'none' ); endif; ?> </main><!-- .site-main --> </div><!-- .content-area --> <?php get_sidebar(); ?> <?php get_footer(); ?> |
Для отображения внутренностей товарного блока, в соответствии со структурой родительского шаблона создадим в папке "template-parts" файл "content-product.php":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php /** * The template part for displaying content * * @package WordPress * @subpackage Twenty_Sixteen * @since Twenty Sixteen 1.0 */ ?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <header class="entry-header"> <?php if (is_sticky() && is_home() && !is_paged()) : ?> <span class="sticky-post"><?php _e('Featured', 'twentysixteen'); ?></span> <?php endif; ?> <?php the_title(sprintf('<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h2>'); ?> </header><!-- .entry-header --> <?php twentysixteen_post_thumbnail(); ?> <div class="entry-price"> <?php if (get_field('tp_price_sale')) : ?> <span class="ep-price"><?php echo get_field('tp_price') ?></span> <span class="ep-pricesale"><?php echo get_field('tp_price_sale') ?></span> <?php else : ?> <span class="ep-standart"><?php echo get_field('tp_price') ?></span> <?php endif; ?> </div> <div class="entry-content"> <?php twentysixteen_excerpt(''); ?> </div><!-- .entry-content --> <footer class="entry-footer" style="display: none;"> <?php twentysixteen_entry_meta(); ?> <?php edit_post_link( sprintf( /* translators: %s: Name of current post */ __('Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen'), get_the_title() ), '<span class="edit-link">', '</span>' ); ?> </footer><!-- .entry-footer --> <div class="btn-order" onclick="cfbuyitnow('<?php echo get_the_title() ?>', '<?php echo esc_url(get_permalink()) ?>')"> Buy it now </div> </article><!-- #post-## --> |
Здесь удален вывод короткого описания поста формирующегося на основе его содержания, вместо этого под картинкой товара выведено краткое описание заполняемое в поле "Отрывок".
В блоке "entry-price" - были вызваны поля добавленные с помощью ACF, сформирована либо просто цена, либо если есть скидочная цена - обычная цена перечеркивается и отображается рядом со скидочной ценой.
Добавлена кнопка - див с классом "btn-order". Из особенностей, в её в атрибут oncklick вставлена js функция "cfbuyitnow", она нужна будет для запуска всплывающей формы.
Динамическая всплывающая форма (попап/модальное окно) на основе Contact Form 7
Для того чтобы пользователи могли нам сообщать какой товар они собираются купить, а также свои контактные данные нам нужна форма для заполнения таких данных. Но к тому же нам необходимо чтобы в этой форме содержалась и передавалось дополнительная информация, например - ссылка на товар. Для этого будем использовать плагин Contact Form 7, добавив в него немного динамики. Попутно стоит установить плагин Flamingo для того чтобы отправленные формы сохранялись в админке вордпреса.
Установив плагин CF7, создадим в нем отдельную форму с названием "Buy it now". Во вкладку FORM вставим html с парочкой блоков разметки для вставки названия товара, скрытый инпут для передачи ссылки на товар, крестик для закрытие формы, а также исправим размер текстового поля и название кнопки "Отправить":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<div class="cf-buyitnow"> <div class="cf-close">✖</div> <div class="cf-custominfo"> <span class="cf-title">Product: </span><span class="cf-product-name"></span> [text product-url class:cf-product-url] </div> <label> Your Name (required) [text* your-name] </label> <label> Your Email (required) [email* your-email] </label> <label> Subject [text your-subject] </label> <label> Your Message [textarea your-message 40x4] </label> [submit "Order"] </div> |
Для того чтобы протащить ссылку на товар, которая будет добавляться в input с названием "product-url" отредактируем во вкладке Mail тело письма в поле "Message Body":
1 2 3 4 5 6 7 8 9 |
From: [your-name] <[your-email]> Subject: [your-subject] Product: [cf-product-url] Message Body: [your-message] -- This e-mail was sent from a contact form on atlogex.com (https://atlogex.com) |
Теперь нам нужно вывести форму на страницу, будем выводить её в footer c помощью хука "wp_footer". Так как в CSS мы создали фиксированное всплывающее окно (класс "cf-buyitnow"), с отключенным по умолчанию отображением (display:none) , нужно добавить яваскрипт, который будет отображать форму после нажатия кнопки "Купить" и скрывать после нажатия по крестику (класс "cf-close"). Всплытие формы организовано с помощью ранее встреченной функции"cfbuyitnow" на кнопке Купить в файле "content-product.php".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function add_cf7() { echo do_shortcode('[contact-form-7 id="24" title="Buy it now"]'); } add_action('wp_footer', 'add_cf7'); function add_cf7_js() { echo " <script> jQuery(document).on('click', '.cf-close', function () { jQuery('.cf-buyitnow').hide(); }); function cfbuyitnow(name, url) { jQuery('.cf-buyitnow').show(); jQuery('.cf-product-name').text(name); jQuery('.cf-product-url').val(url); } </script> "; } add_action('wp_footer', 'add_cf7_js'); |
Таким образом после нажатия кнопки Купить, в форму добавиться урл покупаемого товара в скрытый input, а в заголовке добавиться имя товара который посетитель собирается заказать.
Custom Post Type UI или WooCommerce
Если говорить об обычной витрине товаров, действия пользователя в которой, завершается отправкой заявки на товар, то Custom Post Type хорошее решение. Когда вам нужно полноценное оформление заказа с корзиной, выбором способа доставки и оплаты, то стоит посмотреть в сторону WooCommerce и подобных ему решений.