Шаблон страницы записи Wordpress

Шаблон страницы записи WordPress

Все страницы сайта — это PHP шаблоны, содержащие HTML разметку с PHP тегами. Здесь будет рассмотрено создание шаблона страницы для отдельной записи — начиная от вордпресс цикла и до построения элементов навигации…

Содержание

Что представляет собой запись?

Каждая запись это отдельный представитель типа поста. Из коробки, есть 2 типа постов — страницы и записи; у каждой свои приколы по отображению — у страниц шаблоны для отображения, записей — форматы

шаблоны и форматы
1 — шаблоны страниц; 2 — форматы записей

Для создания шаблона страницы, в начало файла достаточно добавить комментарий

<?php // Template Name: TemplateName
Code language: HTML, XML (xml)

с форматами постов все немного сложнее…

Чтобы активировать возможность выбора формата, в functions.php на экшн after_setup_theme функцию со следующим содержимым

<?php add_theme_support( 'post-formats', array( 'aside', 'image', 'video', 'quote', 'link', 'gallery', 'audio', ) );
Code language: HTML, XML (xml)

Данный код содержит все допустимые форматы для постов; чтобы получить формат текущего поста используйте функцию get_post_format без аргументов, если ты внутри цикла(о нем позже), или с указанием ID поста.

При создании шаблона для своего типа записей — движок позволяет использовать только схему с форматами. По наименованию: для страниц с заголовком требований нет(если стандартный шаблон, без заголовка — page.php). Для постов и нестандартных типов записей — схема такова single-{post_type}.php, ну или single.php для всех типов кроме страниц(page).

WordPress циклы

Будь-то страница или любой другой тип записи(с условием, что он публичен — смотрите «Создаем свой тип записи. Метадата, роли пользователей, таксономии«) его вывод будет начат с цикла. В принципе, тип записей может быть и непубличным, но тогда его нужно будет принудительно доставать, что, я считаю, нехорошо. Итак, цикл(иногда его называют loop, поскольку это перевод) будет выглядеть так

<?php if (have_posts()) { while (have_posts()) { the_post(); // post content } }
Code language: HTML, XML (xml)

Естественно, что в начале выводится шапка(get_header) и подвал(get_footer) в конце. Касательно наполнения цикла — принято подключать кусочек шаблона(отдельный файл) при помощи get_template_part($patth), содержащий разметку страницы.

Элементы страницы

Здесь я рассмотрю основные элементы сингл-поста, которые применимы как к записям, так и страницам и прочим типам.

Изображение записи

Для начала — нужно включить их поддержку — это делает следующий код

<?php add_action( 'after_setup_theme', 'themeslug_setup_theme' ); function themeslug_setup_theme(){ add_theme_support( 'post-thumbnails' ); }
Code language: HTML, XML (xml)

После этого, на странице редактирования записи появиться такой метабокс

thumbnail metabox Шаблон страницы записи WordPress

Теперь о том, как сохраняется загруженное изображение. По умолчанию, при сохранении , сохраняется оригинал и три нарезанных картинки из оригинала. Перейдя по «Settongs > Media» размеры этих изображений можно менять. Чтобы отключить нарезку достаточно выставить размеры в 0. Также, можно задать свой размер для кадрирования

<?php add_action( 'after_setup_theme', 'custom_size' ); function custom_size() { add_image_size( 'custom-size', 100, 100 ); }
Code language: HTML, XML (xml)

Теперь мы имеем 2 варианта по получению установленного изображения; первый — это получение url на оригинал изображения; второй — получение всего img-тега

<?php // Получение url изображения $src = esc_url(get_the_post_thumbnail_url()); // вывод url изображения the_post_thumbnail_url(); // Получение img-тега $img = get_the_post_thumbnail(); // вывод img-тега the_post_thumbnail();
Code language: HTML, XML (xml)

Приведенный выше код работает только внутри вордпресс-цикла, иначе, в качестве первого аргумента, следует указать ID поста. Но функции вывода работают только в цикле. Размеры кадров я упомянул в предыдущем абзаце к тому, что в данных функциях(получение во втором, вывод первым) можно указывать в виде аргумента название размеров. Стандартно full(оригинал), large(1024px*1024px), medium(300px*300px) и thumbnail(150px*150px). Также, вместо строки с названием размера, можно указать массив с шириной и высотой; при этом, при первой загрузке страницы с новым размером, будет создан и сохранен новый кадр.

Касательно получения и выведения img-тега. Последним аргументом в функцию можно передать массив атрибутов тега. Поскольку, в данной функции задается дефолтное значение этого аргумента, то задать можно только такие атрибуты — src, class и alt.

Таксономии

Будь-то стандартные, либо же кастомные таксономии, древовидные они или нет — вывод их одинаков

<?php $terms = wp_get_post_terms( $post_id, $taxonomy, $args );
Code language: HTML, XML (xml)

Первые 2 аргумента понятны, третий это поля, которые будут возвращены; по умолчанию all, возможные значения — names ids.

В случаи, если нужны особые условия применить к получаемым данным, можно применить

<?php $terms = wp_get_object_terms($object_ids, $taxonomies, $args);
Code language: HTML, XML (xml)

здесь $object_ids это ID записи, а вот на $args, пожалуй, поподробнее:

orderby -поле, по которому сортировать порядок вывода:

  • поиск в полях терминов — term_id, name, slug, term_group;
  • по полям таксономии терминов — id(поле term_taxonomy_id в таблице БД), description, parent, count(количество терминов в таксономии);
  • среди полей таблицы term_relationships — term_order;
  • по полям меты — meta_value_num(количеству полей meta_value) и по значению meta_key

Можно и вообще отключить сортировку установив значение в ‘none’. Ключ order устанавливает порядок сортировки(ASK/DESC).

Также, в этом массиве можно задать множество других параметров поиска. К примеру, наличие/отсутствие/равенство метаполей, вложенность, древовидность и т.д. Получаем ссылку на архив термина

<?php $url = esc_url(get_term_link( $term, $taxonomy ));
Code language: HTML, XML (xml)

Контент и метадата

Для начала выведем заголовок записи

<?php // вывод the_title('<h1>', '</h1>'); // получение в переменную $title = esc_html(get_the_title());
Code language: HTML, XML (xml)

В случаи с выведением на страницу, указывать аргументы не обязательно, но в такой записи заголовок будет обрамлен H1-тегом. Не много о том, почему не стоит вытягивать post_title с обьекта WP_Post — потому, что запись может быть личной или защищенной паролем; при правильном выводе эти статусы являются частью заголовка, при неправильном — этот функционал придется дублировать… а это плохо!

Что касается контента, там все аналогично(почти)

<?php // вывод the_content(); // получение в переменную $content = get_the_content();
Code language: HTML, XML (xml)

Опять таки, можно вытянуть контент с обьекта WP_Post, но в функции get_the_content происходит ряд об робок другими фильтрами…

Следующее, это вывод/получение даты, а также ссылки на ее архив

<?php $format = get_option( 'date_format' ); //вывод the_date( $format, $before, $after ); // получение $date = the_date( $format, $before, $after, false ); // или $date = get_the_date( $format, $post ); // ссылка на архив $url = esc_url(get_day_link( $year, $month, $day ));
Code language: HTML, XML (xml)

Здесь, как и в случаи с заголовком, $before и $after это текст(включая html) до и после даты.

Пару слов о метадате поста. Вся дополнительная информация к посту — это метадата. Чтоб ее достать достаточно знать метаключ за коим она храниться

<?php $metadata = get_post_meta($post_id, $metakey, true);
Code language: HTML, XML (xml)

поскольку одинаковых метаключей к одной записи может быть много, то данные извлекаются в виде массива; если поле одно — можно сразу его извлечь, указав true третьим аргументом — иначе, по умолчанию, будет false.

Навигация

Под контентом поста принято делать ссылки на предыдущий и следующий посты. Делается это следующим кодом

<?php $nav = get_the_post_navigation($args);
Code language: HTML, XML (xml)

Переменная будет содержать следующую разметку

<nav class="navigation post-navigation" role="navigation" aria-label="Posts"> <h2 class="screen-reader-text">Post navigation</h2> <div class="nav-links"> <div class="nav-previous"> <a href="{prevPostLink}" rel="prev">Prev Post Title</a> </div> <div class="nav-next"> <a href="{nextPostLink}" rel="next">Next Post Title</a> </div> </div> </nav>
Code language: HTML, XML (xml)

Через аргумент функции моно кастомизировать только атрибуты class у и aria-label тега nav, а также то, что в ссылке. Для этого в массиве $args есть ключи prev_text(может содержать html-теги), next_text(тоже), aria_label и class.

Если же такой уровень кастомизации не достаточен и нужна своя разметка — делаем следующее: получаем а-теги

<?php $prevLink = get_previous_post_link(); $nextLink = get_next_post_link();
Code language: HTML, XML (xml)

Комментарии

В вордпресс принято поключать комментарии таким образом

<?php if ( comments_open() || get_comments_number() ) : comments_template(); endif;
Code language: HTML, XML (xml)

Здесь проверяется открытые ли комментарии у поста и их наличие. При выполнении хотя б одного условия — будут загружены стандартные форма комментирования и список комментов, которые можно перезаписать в файле comments.php темы.

Рекомендую сделать также, это избавит от некоторых проблем. Дальше, создаем файл comments.php и пишем в него.

Форма комментариев

Здесь ситуация похожа на ситуацию с навигацией: форму комментария строит отдельная функция.

<?php comment_form( $args, $post_id );
Code language: HTML, XML (xml)

внутри цикла $post_id можно пропустить. При пустом $args получим следующий html

<div id="respond" class="comment-respond"> <h3 id="reply-title" class="comment-reply-title">Leave a Reply <small><a rel="nofollow" id="cancel-comment-reply-link" href="{cancelReplyLink}" style="display:none;">Cancel reply</a></small></h3> <form action="{actionLink}" method="post" id="commentform" class="comment-form" novalidate=""> <!-- if current user logged in --> <p class="logged-in-as"> <a href="{profileLink}" aria-label="Logged in as admin. Edit your profile.">Logged in as admin</a>. <a href="nonce=dc4f1aa958">Log out?</a> </p> <!-- endid --> <p class="comment-form-comment"> <label for="comment">Comment</label> <textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required="required"></textarea> </p> <!-- if current user not logged in --> <p class="comment-form-author"> <label for="author">Name <span class="required">*</span></label> <input id="author" name="author" type="text" value="" size="30" maxlength="245" required="required"> </p> <p class="comment-form-email"> <label for="email">Email <span class="required">*</span></label> <input id="email" name="email" type="email" value="" size="30" maxlength="100" aria-describedby="email-notes" required="required"> </p> <p class="comment-form-url"> <label for="url">Website</label> <input id="url" name="url" type="url" value="" size="30" maxlength="200"> </p> <p class="comment-form-cookies-consent"> <input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"> <label for="wp-comment-cookies-consent">Save my name, email, and website in this browser for the next time I comment.</label> </p> <!-- endif --> <p class="form-submit"> <input name="submit" type="submit" id="submit" class="submit" value="Post Comment"> <input type="hidden" name="comment_post_ID" value="10" id="comment_post_ID"> <input type="hidden" name="comment_parent" id="comment_parent" value="0"> </p> <input type="hidden" id="_wp_unfiltered_html_comment_disabled" name="_wp_unfiltered_html_comment" value="f6a52e0808"><script>(function(){if(window===window.parent){document.getElementById('_wp_unfiltered_html_comment_disabled').name='_wp_unfiltered_html_comment';}})();</script> </form> </div>
Code language: HTML, XML (xml)

Но, в отличие от навигации, здесь можно провести полную кастомизацию через функцию. Для этого заполним массив $args:

  • ключ fields — массив шаблонов(начиная с тега р), содержащий поля формы комментария за ключами author, email и url;
  • comment_field — содержит шаблон, непосредственно, поля ввода комментария;
  • must_log_in — текст для не залогиненных пользователей при обязательном логировании, чтоб оставить коммент;
  • logged_in_as — текст для залогиненного пользователя;
  • submit_field — шаблон поля отправки формы.

В принципе, для полной кастомизации этого достаточно, однако, в аргументе есть еще дополнительные поля для более тонкой настройки… и не только вида.

Немного о добавлении своих полей в форму комментирования: для добаления поля — фильтром comment_form_fields изменяй массив полей

<?php add_filter('comment_form_fields', 'custom_comment_form_field'); function custom_comment_form_field($comment_fields) { $custom_field['custom_field'] = '<p><label>My query<input name="my_query"></label></p>'; // insert $custom_field after name(index = 1) return array_merge( array_slice($comment_fields, 0, 2), $custom_field, array_slice($comment_fields, 2) ); }
Code language: HTML, XML (xml)

после этого экшном wp_insert_comment нужно сохранить данное поле

<?php add_action('wp_insert_comment', 'wp_insert_custom_comment_field', 10, 2); function wp_insert_custom_comment_field($id, $comment) { if (isset($_POST['my_query'])) { update_comment_meta($id, 'my_query', sanitize_text_field($_POST['my_query'])); } }
Code language: HTML, XML (xml)
Список комментариев

Следующая вещь, которая, по сути, есть продолжением формы комментариев — это список ранее оставленных комментариев. Он также выводится функцией

<?php wp_list_comments($args, $comments);
Code language: HTML, XML (xml)

При использовании стандартной схемы аргумент $comments указывать не нужно. Иначе, $comments = get_comments() в котором нужно формировать свой массив аргументов. При пустом $args wp_list_comments выведет следующую разметку для каждого коммента

<li id="comment-1" class="comment even thread-even depth-1"> <article id="div-comment-1" class="comment-body"> <footer class="comment-meta"> <div class="comment-author vcard"> <img alt="" src="{avatar}" srcset="{avatar}" class="avatar avatar-32 photo" height="32" width="32" loading="lazy"> <b class="fn"><a href="https://wordpress.org/" rel="external nofollow ugc" class="url">A WordPress Commenter</a></b> <span class="says">says:</span> </div><!-- .comment-author --> <div class="comment-metadata"> <a href="{linkToComment}"> <time datetime="{commentTime}"> Comment Time </time> </a> <span class="edit-link"> <a class="comment-edit-link" href="{linkToEditComment}">Edit</a> </span> </div><!-- .comment-metadata --> </footer><!-- .comment-meta --> <div class="comment-content"> <p>Comment Text</p> </div><!-- .comment-content --> <div class="reply"> <a rel="nofollow" class="comment-reply-link" href="{linkToReply}" data-commentid="1" data-postid="1" data-belowelement="div-comment-1" data-respondelement="respond" data-replyto="Reply to A WordPress Commenter" aria-label="Reply to A WordPress Commenter">Reply</a> </div> </article><!-- .comment-body --> </li>
Code language: JavaScript (javascript)

Здесь самый широкий, даже, наверное, излишний, способ кастомизации — и все доступно через функцию:

  • max_depth — максимально разрешенная вложенность комментов;
  • style — стиль вывода дерева — ul, ol(по умолчанию) или div. Данный аргумент имеет значение для вложенных комментариев, поскольку сама функция должна быть при вызове обнесенная контейнером отдельно;
  • type — отображаемый тип комментариев;
  • per_page — в случаи необходимости пагинации — количество комментариев на странице;
  • page — страница пагинации коммента;
  • avatar_size — размер аватара комментатора
  • callback — функция-строитель каждого комментария, без закрывающего тега;
  • end-callback — строитель закрывающего тега;
  • walker экземпляр класса-строителя дерева комментариев.

Есть еще много ключей для «мелкой настройки» этой функции, но главное уже приведено. По поводу того, что функции открывающего и закрывающего тега разделены — тут, как и в меню, есть вложенность, и для ее реализации сделано так.

Сайдбар

Сайдбар — это место для вывода виджетов, виджет-зона. У нее, также как и у комментов, свой стандарт для выведения. В шаблоне страницы ставят такой код

<?php get_sidebar($slug);
Code language: HTML, XML (xml)

данный код подключит sidebar.php из темы; если $slug не пустая строка, то подключит sidebar-{$slug}.php

<?php if (is_active_sidebar($slug)) { dynamic_sidebar($slug); }
Code language: HTML, XML (xml)

$slug здесь это идентификатор виджет-зоны, который был указан при ее регистраци в функции register_sidebar().

Заключение

Рассмотрены все стандартные элементы шаблон страницы записи WordPress. О чем стоит упомянуть еще — так это о том, что в обертке каждого поста должны быть теги

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <!-- post content --> </article>
Code language: PHP (php)

это анкор для ссылки в шапке. Считаю, что рассказал вам обо всех элементах сих страниц, так как дополнительные — это виджеты, вставляемые в сайдбар. И кстати, некоторые из этих элементов встречаются и на страницах других типов.