Transients API: Часть 3. Использование transients для ускорения работы меню WordPress

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

Кэширование навигационных меню

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

Давайте в качестве примера рассмотрим мой исходный код для получения меню WordPress:

<?php 
if ( has_nav_menu( 'header-menu' ) ) {
	wp_nav_menu( array(
		'menu'    => '33',
		'depth'      		=> 3,
		'container'  		=> 'nav',
		'menu_class' 		=> 'nav nav-pills',
		'fallback_cb' 		=> 'wp_page_menu',
		'walker' 		=> new wp_bootstrap_navwalker()
	) );
}

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

Теперь давайте взглянем на измененный код, который я опишу строка за строкой чуть ниже:

<?php
$header_menu_query = get_transient( 'header_menu_query' );
if( $header_menu_query === false ) {
	if ( has_nav_menu( 'header-menu' ) ) {
		$header_menu_query = wp_nav_menu( array(
			'menu'   			=> '33',
			'depth'      		=> 3,
			'container'  		=> 'nav',
			'menu_class' 		=> 'nav nav-pills',
			'fallback_cb' 		=> 'wp_page_menu',
			'walker' 			=> new wp_bootstrap_navwalker(),
			'echo'				=> 0,
		) );
	}
	set_transient( 'header_menu_query', $header_menu_query, 60*60*24 );
}
echo $header_menu_query;

В строке 2 мы задаем нашу переменную $header_menu_query равной значению transient с таким же именем через get_transient(). В строке 3 мы проверяем, существуют ли данные transient. Если нет (потому что они не были созданы или уже просрочены и удалены), то мы совершаем запрос на получение меню WordPress. В строке 5 мы задаем нашу переменную равной результату запроса wp_nav_menu.

Учитывая тот факт, что в примере с произвольными запросами мы не меняли сам запрос, нам нужно будет внести небольшие коррективы в функцию wp_nav_menu. По умолчанию wp_nav_menu выводит результат запроса через echo (обычно именно это и требуется), однако мы хотим вернуть данные в виде PHP для сохранения в transient, поэтому нам нужно будет добавить аргумент ‘echo’ => 0 в функцию, как показано в строке 12. Остальная часть запроса осталась неизменной.

В строке 15 мы берем результат запроса и задаем наш transient с этими данными через set_transient(), чтобы они могли использоваться при следующей загрузке страницы. Опять же, вы заметите, что я задал максимальное время истечения (24 часа) – об этом чуть позже.

В строке 17 нам нужно сделать небольшое добавление: поскольку ранее функция wp_nav_menu автоматически выводила меню на экран, а мы изменили запрос для возвращения его в виде PHP, нам нужно вывести через echo итоговый результат. Именно это мы и делаем в данной строке.

Обновление transient

Как в примере с произвольными запросами, мы задали максимальное время истечения для данных, по прошествии которого мы хотим заменить их. Меню WordPress не изменяются часто, поэтому время истечения можно было задать достаточно длительным. Одного дня в данном случае вполне достаточно, чтобы совершать ежедневные проверки, не влияя на производительность (один запрос к базе данных в день не будет даже замечен).

Однако мы хотим заранее удалить данные, если мы знаем, что они были изменены. Чтобы сделать это, я написал еще одну функцию, которую я поместил в свой функциональный плагин, однако ее можно было бы добавить в файл functions.php. Вот какой вид она имеет:

<?php // MENU TRANSIENTS
 
function hpc_delete_menu_transients() {
	delete_transient( 'header_menu_query' );
	delete_transient( 'footer_menu1_query' );
	delete_transient( 'footer_menu2_query' );
}
 
add_action( 'wp_update_nav_menu', 'hpc_delete_menu_transients' );

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

Здесь мы просто используем функцию delete_transient() для удаления всех моих transients для меню всякий раз, когда меню обновлено (у меня задано два дополнительных меню, footer_menu1 и footer_menu2, к которым я применяю аналогичную технику).

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

Источник: doitwithwp.com

Блог про WordPress
Комментарии: 2
  1. Kolass

    Добрый день. А как написать класс walker для меню. Если я хочу просто добавить дивы определенных классов перед меню второго уровня?

    1. Дмитрий (автор)

      Здравствуйте. Можете посмотреть вот здесь, как реализован класс walker:

      http://shinraholdings.com/62/custom-nav-menu-walker-function/#example-code

      В качестве дополнительной информации советую почитать статью в кодексе: http://codex.wordpress.org/Function_Reference/wp_nav_menu

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

Получать новые комментарии по электронной почте.