Title, description, keywords и h1 для категорий (рубрик) WordPress

Всем привет! Сегодня на seo-mayak.com я продолжу серию статей, посвященных категориям WordPress.

Займемся мы непростой на первый взгляд задачей, а именно, возьмем и сделаем независимые title, description и keywords для категорий или рубрик, как удобно.

Кроме того мы разберем функционал, который позволит вывести заголовок h1, отличный от названия категории.

Согласитесь, страница редактирования категорий в WordPress как-то обиженна разработчиками, хотя, кое-что они все же предусмотрели. Читайте статью до конца, будет интересно!

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

Я бы рад помочь многим, но в каждую конкретную ситуацию надо вникать, а на это у меня к сожалению просто нет времени. На всех меня все равно не хватит.

А сейчас пред нами стоит задача сделать независимые title, description, keywords и h1, с возможностью прописывать их отдельно на странице редактирования категорий. Поехали!

Создаем поля: title, description, keywords и h1

Для осуществления задуманного нам потребуется открыть в текстовом редакторе (рекомендую Notepad++, а также FTP клиент Notepad++) файл functions.php, что лежит в папке с темой.

В самое начало, после знака «<?php» вставляем следующее:

  add_action("category_edit_form_fields", 'mayak_category_meta');  function mayak_category_meta( $term ) {  	?>  		<tr class="form-field">  			<th scope="row" valign="top"><label>Заголовок (title)</label></th>  			<td>  				<input type="text" name="mayak[title]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'title', 1 ) ) ?>"><br />  				<p class="description">Не более 60 знаков, включая пробелы</p>  			</td>  		</tr>  		<tr class="form-field">  			<th scope="row" valign="top"><label>Заголовок h1</label></th>  			<td>  				<input type="text" name="mayak[h1]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'h1', 1 ) ) ?>"><br />  				<p class="description">Заголовок страницы</p>  			</td>  		</tr>  		<tr class="form-field">  			<th scope="row" valign="top"><label>Ключевые слова</label></th>  			<td>  				<input type="text" name="mayak[keywords]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'keywords', 1 ) ) ?>"><br />  				<p class="description">Ключевые слова (keywords)</p>  			</td>  		</tr>  	<?php  }  

В итоге, в админке на странице редактирования категорий должны появиться три новых поля:

Вы наверное заметили, что я упустил поле description. Мы сейчас его отдельно вставим в функцию, чтобы Вам было понятно, как добавлять новые поля.

Прямо в функции, после любого закрывающего тега «</tr>» вставляем код поля «description»:

<tr class="form-field">  <th scope="row" valign="top"><label>Краткое описание (description)</label></th>  <td>  <input type="text" name="mayak[description]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'description', 1 ) ) ?>"><br />  <p class="description">Краткое описание (description)</p>  </td>  </tr>

Таким образом мы создали четыре дополнительных поля:

Куда мы можем теперь записывать определенные данные. Такие поля еще называются «произвольными полями».

Радоваться конечно рано, так как пока эти поля «мертвые», т.е. написать в них можно что угодно, только вот после обновления страницы поля опять станут пустыми.

Почему так? Это потому, что мы создали только «каркас» и данные пока нигде не сохраняются. А схоронятся они должны где? Правильно, в базе данных.

Давайте это дело поправим. Ниже нашей первой функции вставляем еще одну:

function mayak_save_meta( $term_id ) {  	if ( ! isset($_POST['mayak']) )  		return;  	$mayak = array_map('trim', $_POST['mayak']);  	foreach( $mayak as $key => $value ){  		if( empty($value) ){  			delete_term_meta( $term_id, $key );  			continue;  		}  		update_term_meta( $term_id, $key, $value );  	}  	return $term_id;  }  add_action("create_category", 'mayak_save_meta');  add_action("edited_category", 'mayak_save_meta');

Теперь, если попробовать обновить страницу редактирования рубрики, то все, что мы написали в новых полях, останется на месте.

Ну хорошо, все вроде сохраняется, и понятно, что сохраняется в БД. Но где именно, в какой таблице?

Давайте этот момент разберем немного подробней.

Таблица wp_termmeta

С выходом версии 4.4, разработчиками WordPress в базу данных была внедрена новая таблица, которая называется wp_termmeta. Вот она:

Получается, что появилась еще одна, уже четвертая таблица в базе данных WordPress, которая так или иначе относится к категориям. О таблицах: wp_terms, wp_term_taxonomy и wp_term_relationships я подробно писал тут.

Если отрыть таблицу, то мы увидим, что она состоит из четырех колонок (полей):

Если таблица пуста, то она выглядит следующим образом:

Давайте разберемся, что это за поля, и что в их записывается.

meta_id — Порядковый идентификатор, который присваивается каждой связке двух полей meta_key -> meta_value (ключ -> значение ключа).

term_id — Идентификатор категории, к которой прикрепляется связка полей meta_key -> meta_value.

meta_key — Непосредственно сам ключ. Под ключем подразумевается кодовое слово, которое может состоять из произвольного набора латинских символов. Для чего создается это кодовое слово, мы поймем немного позже, а пока скажу, что к каждому «ключу» обязательно привязывается «значение», содержимое поля meta_value.

meta_value — Значение ключа, которым может быть что угодно. Ниже, к данному полю мы еще вернемся, так что будет понятней, надеюсь.

Теперь давайте заполним поля и посмотрим, что пропишется в таблице wp_termmeta:

Смотрим в таблицу:

Итак, в поле meta_id прописывается присвоенный БД идентификатор, который закрепляется за каждой связкой ключ->значение, начиная с единицы.

В поле term_id указывается ID категории, к которой будут привязаны связки ключей и их значений.

На поле meta_key остановимся немного подробней. Откуда, например, ваялся ключ «title»?

Что такое key (ключ) и откуда он берется

Ключ «title» был указан мной при составлении первой функции-каркаса. Обратите внимание на строчку №6:

<input type="text" name="mayak[title]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'title', 1 ) ) ?>">

Надеюсь становится понятно, что ключ «title» — это ничто иное, как имя поля —name="mayak[title]" то, что в квадратных скобках. Имя может быть любым набором англ. символов.

Все что будет вписано в поле с именем [title], автоматически станет значением ключа «title» и будет занесено в БД, в колонку meta_value таблицы wp_termmeta.

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

Подведем некоторые итоги: Мы создали поля для ввода данных и имеем возможность сохранять эти данные в базе данных, причем сохраняться данные будут точно там, где им будет указано. Указано кем? Действительно, почему данные записались в нужное место, кто руководил процессом?

В качестве режиссера сего действа выступают сразу три функции

add_term_meta() — запись;
update_term_meta() — перезапись (обновление);
delete_term_meta() — удаление.

Есть еще одна функция, которая называется get_term_meta(). Эта функция получает из БД, а конкретно из таблицы wp_termmeta, определенные данные (связки ключ->значение), которые можно вывести на экран или продолжить с ними дальнейшие операции.

Итак, мы знаем где хранятся нужные нам данные, давайте теперь попробуем их от туда достать и вывести в нужном месте. Начнем пожалуй с заголовка title.

Отдельный заголовок title для категорий

Сам WordPress и все SEO плагины берут данные для title из заголовка категории, вернее из функции, которая выводит этот заголовок на экран. Называется функция single_term_title().

На заметку! До версии WordPress 3.1.0, вместо функции single_term_title(), использовалась функция single_cat_title().

Работу этой функции нам и надо будет подкорректировать, чтобы решить поставленную задачу.

Как мы это сделаем? Все просто! Функция single_term_title() имеет в своем арсенале хук single_cat_title, с помощью которого мы подменим заголовок категории на наш title, причем прямо перед выводом его на экран.

Для этого в файл funtions.php вставляем такую функцию:

function mayak_filter_single_cat_title($term_name) {      $terms = get_category( get_query_var('cat'));      $cat_id = $terms->cat_ID;      $term_name = get_term_meta ($cat_id, 'title', true);  	return $term_name;	  }  add_filter('single_cat_title', 'mayak_filter_single_cat_title', 10, 1 );

Теперь, если мы заполним поле title, то именно с этого поля WordPres и все SEO плагины будут брать заголовок для поисковой выдачи:

Но здесь есть один нюанс. Если поле title по каким-то причинам не будет заполнено, то замены никакой не будет и вместо заголовка title будет пустое место:

Мне показалось такое положение дел нежелательным, так как после внедрения данного функционала, в один миг пропадут все заголовки title взятые из названия рубрик, так как новые поля title изначально будут пустыми.

Чтобы предотвратить подобную ситуацию, я решил составить еще одну функцию, которая при пустом поле title, будет брать заголовок из названия категории:

function mayak_single_cat_title ($term_name){      if(empty($term_name)){  	    $terms = get_category( get_query_var( 'cat' ));  	    $cat_id = $terms->cat_ID;  	    $term_name = get_cat_name($cat_id);  	}  	return $term_name;  }  add_filter( 'single_cat_title', 'mayak_single_cat_title', 10, 1 ); 

Теперь должно быть все в порядке:

По-моему подстраховка в этом случаи не помещает. Идем дальше.

Отдельный заголовок h1 для категории

Стоит сказать, что заголовок категории не обязательно должен быть обернут в теги h1, ничего страшного не будет, если это будет тег h2. Более подробно свои мысли по этому поводу я выражал здесь.

Вы наверняка заметили, что вместо заголовка категории, бравшегося из названия, теперь отображается содержимое поля title. У меня это выглядит так:

Так получилось из-за нашего вмешательства в функцию single_term_title(). Помните мы заголовок подменили?

Так конечно не должно быть и ситуацию надо дорабатывать, поэтому придется создать свою функцию вывода заголовка категории, вернее две функции.

Сначала нам надо получить из базы данных стандартный заголовок категории, но в обход функции single_term_title(), так как она у нас уже занята другим делом, а именно выводом заголовка title.

Для этого файл functions.php вставляем:

function mayak_cat_caption($caption) {  	$terms = get_category( get_query_var( 'cat' ));  	$cat_id = $terms->cat_ID;  	$caption = get_cat_name($cat_id);      echo $caption;   }

Теперь мы имеем «дубликат» заголовка категории, но для чего он нам нужен? А нужен он нам будет опять же для подстраховки. Если вдруг поле h1 окажется пустым, то будет выведен стандартный заголовок категории, т.е наш дубликат.

А вот и сама функция вывода отдельного заголовка h1:

function mayak_cat_h1($name_cat) {  	$terms = get_category( get_query_var( 'cat' ));  	$cat_id = $terms->cat_ID;  	$name_cat = get_term_meta ( $cat_id, 'h1', true );      echo $name_cat;  	if(empty($name_cat)){  	   echo	mayak_cat_caption($caption);  	}  }

Далее, ищем в папке с темой файлы archive.php или categore.php, зависит от шаблона. В этих файлах ищем теги заголовка категории (это может быть h1 или h2) и заключенную в них функцию:

<?php single_term_title() ?>

У кого тема старая, то ищем:

<?php single_cat_title() ?>

И заменяем на только что созданную:

<?php mayak_cat_h1($name_cat) ?>

Проверим результат:

Заполняем поле:

Все работает. Если что-то не получается, прежде чем задавать вопросы, внимательно все проверьте. Функций много, поэтому легко запутаться и получить ошибки. Идем дальше:

Отдельный description для категорий

Если Вы пользуетесь SEO плагинами, например All in One SEO Pack, то они выводят в качестве description для категорий первые 160 символов и текста, т.е. из поля «Описание». Меня лично это вполне устраивает.

Но если кто-то хочет иметь возможность самостоятельно заполнять краткое описания для категории, то в плагинах эту функцию надо отключить, чтобы description не дублировался.

Например в All in One SEO Pack можно отключить вывод description только для всего сайта, вот так:

function mayak_remove_seo_description( $data ){  return false;  }  add_filter( 'aioseop_description', 'mayak_remove_seo_description' );

Отдельно для категорий, без правки кода самого плагина, вывод description не отключается, по крайней мере у меня не получилось. Если у кого хватило ума это сделать, буду рад пообщаться в комментариях.

Итак, выводим отдельный description для категорий. Функция:

  function mayak_cat_description($description){  	if(is_category()){  	$desc = get_category( get_query_var( 'cat' ));  	$category_id = $desc->cat_ID;  	$description = get_term_meta ( $category_id, 'description', true );  	if(!empty($description)){  	$meta = '<meta name="description"  content="'.$description.'" />'."n";  	}      else {		     	   $description = wp_filter_nohtml_kses(substr(category_description(), 0, 280));  	   $meta = '<meta name="description"  content="'.$description.'" />'."n";	     	}  	echo $meta;  	}  }  add_action('wp_head', 'mayak_cat_description', 1, 1);  

Вот и все! Смотрим результат:

Все встало на места, чего и добивались. Если по каким-то причинам поле description не будут заполнено, то автоматически будет взято 160 символов из текста описания категории.

Нам осталось вывести ключевые слова из одноименного поля.

Отдельный keywords для категорий

Нужны или нет meta keywords для сайта, споры не утихают по сей день! Гугл и Яндекс давно дали понять, что эти meta их больше не интересуют. Однако ничего неизвестно, как на это смотрит Mail.ru и другие поисковики среднего формата, поэтому считаю целесообразным пока не пренебрегать meta keywords.

Далее я буду многословен. Функция:

  function mayak_cat_keywords($keywords){  	if(is_category()){  	$terms = get_category( get_query_var( 'cat' ));  	$cat_id = $terms->cat_ID;  	$keywords = get_term_meta ( $cat_id, 'keywords', true );  	echo ''."n";  	}  }  add_action('wp_head', 'mayak_cat_keywords', 1, 1);  

Результат:

Все должно работать на ура! Но если вдруг вы заметили ошибки, или недочет в функционале, прошу, напишите об этом в комментариях или мне на почту, буду Вам благодарен!

В следующей статье я расскажу, как добавить и закрепить за категорией уникальную картинку. Естественно будет представлен весь функционал, так что надеюсь будет интересно.

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

До встречи!

С уважением, Виталий Кириллов

Статьи по теме:

Редактор для категорий (рубрик), меток и произвольных таксономий
Шаблоны для категорий WordPress. Как сделать каталог из рубрики
Категории WordPress — термы и таксономии
wp_list_categories() — как выводить рубрики WordPress

Источник