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

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

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

Содержание

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

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

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

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

<?php
// Template Name: TemplateName

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

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

<?php
	add_theme_support(
		'post-formats',
		array(
			'aside',
			'image',
			'video',
			'quote',
			'link',
			'gallery',
			'audio',
		)
	);

Данный код содержит все допустимые форматы для постов; чтобы получить формат текущего поста используйте функцию 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
    }
}

Естественно, что в начале выводится шапка(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' );
}

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

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

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

<?php
add_action( 'after_setup_theme', 'custom_size' );
function custom_size() {
	add_image_size( 'custom-size', 100, 100 );
}

Теперь мы имеем 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();

Приведенный выше код работает только внутри вордпресс-цикла, иначе, в качестве первого аргумента, следует указать 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 );

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

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

<?php
$terms = wp_get_object_terms($object_ids, $taxonomies, $args);

здесь $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 ));

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

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

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

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

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

<?php
// вывод
the_content();
// получение в переменную
$content = get_the_content();

Опять таки, можно вытянуть контент с обьекта 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 ));

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

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

<?php
$metadata = get_post_meta($post_id, $metakey, true);

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

Навигация

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

<?php
$nav = get_the_post_navigation($args);

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

<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>

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

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

<?php
$prevLink = get_previous_post_link();
$nextLink = get_next_post_link();

Комментарии

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

<?php
if ( comments_open() || get_comments_number() ) :
	comments_template();
endif;

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

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

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

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

<?php
comment_form( $args, $post_id );

внутри цикла $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>

Но, в отличие от навигации, здесь можно провести полную кастомизацию через функцию. Для этого заполним массив $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)
    );
}

после этого экшном 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']));
    }
}
Список комментариев

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

<?php
wp_list_comments($args, $comments);

При использовании стандартной схемы аргумент $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>

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

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

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

Сайдбар

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

<?php
get_sidebar($slug);

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

<?php
if (is_active_sidebar($slug)) {
    dynamic_sidebar($slug);
}

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

Заключение

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

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

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

Поделиться
  •  
  •  
  •  
  •  
  •  

Шаблон страницы записи WordPress: 3 комментария

  1. Можно ли использовать блоки Гутенберга на шаблоне страницы? Так что это может быть мгновенно доступно для использования, когда кто-то меняет шаблон страницы?

    1. Вы о строительстве страницы полностью? или и о контентной части(в смысле, части принадлежащей содержанию поста, а не сайдбара, к примеру)? Если о строительстве всего шаблона, то обратите свой взор на плагины-пэйджбилдеры типа Elementor. Во втором случаи, Гутенберга с лихвой, если будет отсутствовать какой-то блок — ищите расширения для него(их много)

  2. Вам нужно использовать пользовательский тип записи для блоков. Что он делает, так это вы можете зарегистрировать свой собственный шаблон записи с предопределенными блоками в нем. И я верю, что это именно то, что вы ищете. Вот пример этого — Эта функция регистрирует параметр CPT и через шаблон, указывая, какой блок находится внутри него. Вы можете заблокировать(не разрешен внешний блок), свободно заблокировать (разрешены определенные блоки) или разрешить также вставлять другие блоки.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *