WordPress как на ладони
rgbcode is looking for WordPress developers. Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!

Оптимизация производительности WordPress за счет постоянных ссылок (практика)

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

Суть метода

Так как нам нужно избавиться от постоянных генераций ссылок, то логично сгенерировать ссылку и сохранить её где-нибудь, а потом просто её от туда "брать". Сохранять я решил в Базе Данных, в которой, как оказалось, есть даже поле для этого - guid. Впрочем, guid создан не совсем для этого и разработчики не рекомендуют менять guid он создается один раз при публикации поста и затем уже не меняется.

Поле guid таблицы wp_posts создано для хранения там уникального значения - идентификатора записи. Нужен он для идентификации записи в RSS ленте. GUID так и расшифровывается: Globally Unique Identifier - глобальный уникальный идентификатор. По этому полю парсеры RSS определяют обрабатывали они запись или нет.

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

Но, так как RSS уже мало кто пользуется а ссылка записи меняется крайне редко, думаю на это предупреждение можно закрыть глаза и изменять guid - записывать туда постоянную ссылку. Аргументация такая: сейчас RSS пользуются не многие и ссылка эта измениться если переезжать на другой домен или поменять ЧПУ, а это происходит редко, и даже если изменить, ваши читатели увидят последние 10 постов в своем RSS, которые уже были - думаю это не совсем не страшно...

Удобство постоянной генерации заключается в том, что если у нас по каким-то причинам измениться постоянная ссылка на статью, то генерирующиеся ссылки всегда будут оставаться рабочими (актуальными), тогда как ссылки которые записываются, при изменении, могут стать нерабочими. Однако, на деле ссылки практически никогда не меняются, а если уж мы сменили домен сайта или сменили структуру ЧПУ у статей, то перезаписать (создать новые) ссылки в БД очень просто (я сделал мини плагин).

Поле куда мы будем записывать "готовые" постоянные ссылки находится в таблице wp_posts (в ней хранятся все записи) и называется guid. Это поле нигде не используется - только для RSS см. выше. Рассчитано оно как раз для того, чтобы туда записывать готовые permalink-и - туда пишутся иногда готовые пермалинки, а иногда ссылки вида http://example.com/?p=133, причем происходит это в каком-то хаотичном порядке, зависит, вроде, от того публикуется материал до или после записи первого черновика. Да, это и не важно.

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

  1. При публикации/обновлении записи в поле guid таблицы wp_posts записывать постоянную ссылку на статью

  2. При использовании ссылки в шаблоне WordPress не использовать функцию get_permalink(), а брать уже готовую ссылку: $post->guid.

Реализация

Чтобы в БД правильно записывались постоянные ссылки в поле guid, я сделал такой хак, для файла темы functions.php:

add_action( 'save_post', 'guid_write', 100 );
function guid_write( $id ){
	if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE  ) return false;

	if( $id = intval($id) ){
		global $wpdb;
		$wpdb->update( $wpdb->posts, ['guid'=>/*wp_make_link_relative*/( get_permalink($id) ) ], ['ID'=>$id] );
	}

	clean_post_cache( $post_id );
}

Этот хак работает когда пост/страница публикуется, обновляется. Хак так же срабатывает при удаленной публикации через xml-rpc.

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

<?php echo get_permalink() ?>

а

<?php echo $post->guid ?>

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

echo get_permalinks();
echo get_permalinks($post->ID);
the_permalink();
the_permalink($post->ID);

на

echo $post->guid

Важно понимать, что, например, конструкции вида the_permalink(25); или the_permalink($post_id); , где $post_id устанавливается заранее, как ID какого-то поста, менять на echo $post->guid нельзя, потому что такие конструкции получают ссылки на определенный пост, а echo $post->guid выводит ссылку на пост, который в текущий момент находится в глобальной переменной $post.

Кстати, в моих функциях вывода: вывод последних записей, предыдущие из категории также можно и даже нужно заменить get_permalink($pst->ID) на $pst->guid. Я в них специально добавлял в выборку поле guid. Однажды даже забыл поменять на get_permalink() и в комментариях мне припомнили, что функция не чувствительная к пермалинкам smile

Для уже рабочих сайтов, где поля guid уже определены "неправильно"

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

Ремонт guid

Скачать плагин

Fix Guid V1.2
Плагин для просмотра/редактирования поля guid в базе данных WordPress.
Скачано: 146, размер: 2.3 KB

Устанавливается плагин как обычно: копируем файл из архива fix_guid.php в каталог плагинов и активируем его в админке.

После того как поля guid "отремонтированы", плагин можно удалить. Плагин так же умеет грамотно удалять ревизии записей (удаляется все включая авто-сохранения).

Рекомендации

Если у вас структура ЧПУ не содержит тегов %category%, %tag%, %author%, то нет острой необходимости использовать этот прием оптимизации. Однако, если эти теги используются, то этот прием даст отличный эффект.

Тесты

В комментариях меня "спровоцировали" провести тесты, чтобы посмотреть как в действительности влияет на оптимизацию такой способ, вот что получилось:

С ЧПУ вида /%category%/%postname% функция the_permalink() (она же get_permalink(), только без фильтров) затрачивает 0,12 секунды на генерацию 10 ссылок. Тогда как при ЧПУ вида, например, /%year%/%monthnum%/%day%/%postname% уходит всего 0,02 секунды.

Замеры я проводил на своем компе, где, для сравнения, главная страница WordPress 3.0.1 с дефолтной темой генерируется за 1,3 секунды.

Таким образом, если у нас в ЧПУ присутствует %category% и на странице выводиться, скажем 50 уникальных (не повторяющихся) ссылок, то на генерацию этой страницы уйдет плюс 0,6 секунды (0,12*5=0,6), почти пол секунды.

Нужно отметить (я этого раньше не знал), что один раз сгенерировав ссылку WordPress, её кэширует и при повторном вызове the_permalink() для того же поста, ссылка "генерируется" в доли секунды. Имею ввиду это:

//получаем ссылку для поста с ID 25
the_permalink(25); //время 0,012
//получаем ссылку еще раз
the_permalink(25); //время, примерно, 0,0001

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

27 комментариев
Полезные 1 Все
    Войти