# Оптимизация производительности WordPress с помощью постоянных ссылок
В первой части статьи я обсудил теоретические основы работы постоянных ссылок (пермалинков) в WordPress и предложил способы их оптимизации. К сожалению, я не получил предложений от читателей, и прошёл значительный срок, поэтому решил опубликовать свою версию.
## Суть метода
Нам нужно избавиться от постоянной генерации ссылок. Логично генерировать ссылку один раз и сохранять её, чтобы потом просто "брать" оттуда. Я решил сохранить её в базе данных, где, как оказалось, есть специальное поле для этого — guid
. Однако поле guid
не создавалось специально для наших нужд, и разработчики не рекомендуют изменять его. Это поле создаётся один раз, когда пост публикуется, и больше не меняется.
Поле guid
в таблице wp_posts
предназначено для хранения уникального значения — идентификатора записи. Оно необходимо для идентификации записи в RSS-ленте. Акроним GUID расшифровывается как "Глобальный Уникальный Идентификатор". RSS-агрегаторы используют это поле, чтобы решать, обрабатывать запись или нет.
Вот почему разработчики настоятельно не рекомендуют изменять это поле — даже если ваш сайт переехал на другой домен. Если вы измените guid
, ваши читатели RSS могут увидеть множество уже опубликованных материалов.
Но так как очень мало людей пользуются RSS, а ссылки на посты меняются крайне редко, я думаю, мы можем проигнорировать это предупреждение и изменить guid
, сохранив постоянную ссылку там. Ведь эта ссылка изменится только при переезде на другой домен или изменении структуры URL, что бывает крайне редко. И даже если она изменится, ваши читатели все равно увидят последние 10 постов в своих RSS, которые они уже видели — я не думаю, что это страшно.
Преимущество постоянной генерации заключается в том, что если по какой-то причине постоянная ссылка на статью изменится, сгенерированные ссылки всегда останутся рабочими, тогда как сохранённые ссылки могут стать неактивными при изменении. Однако на практике ссылки почти никогда не меняются, и если мы изменили домен сайта или структуру URL, переписать (создать новые) ссылки в базе данных очень просто (я сделал ми��и-плагин для этого).
Поле, куда мы будем записывать "готовые" постоянные ссылки, находится в таблице wp_posts
(где хранятся все записи) и называется guid
. Это поле не используется нигде, только для RSS. Оно как раз предназначено для записи готовых пермалинков — иногда туда записываются готовые ссылки, а иногда ссылки в виде 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
используйте:
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
задан заранее как идентификатор определённого поста, не могут быть изменены на echo $post->guid
, потому что такие конструкции получают ссылки для конкретного поста, в то время как echo $post->guid
выводит ссылку на пост, который в данный момент находится в глобальной переменной $post
.
Кстати, в моих функциях отображения: для вывода последних постов, пре��ыдущих постов из категории, вам также нужно и даже следует заменить get_permalink($pst->ID)
на $pst->guid
. Я специально добавил поле guid
в выборку в них. Однажды я даже забыл изменить его на get_permalink()
, и в комментариях кто-то напомнил мне, что функция не чувствительна к пермалинкам.
Для уже функционирующих сайтов, где поле GUID уже "неправильно" определено
Если сайт уже работает и в нём уже много записей, постоянные ссылки которых записаны "неправильно" в поле guid
, я сделал плагин для таких случаев, чтобы переписать (исправить) поле guid
.
Загрузка плагина
Чтобы скачать плагин, скопируйте файл из архива fix_guid.php
в директорию плагинов и активируйте его в админ-панели. После того, как поля guid
будут "отремонтированы", плагин можно удалить. Плагин также корректно удаляет ревизии постов (всё удаляется, включая автосохранения).
Рекомендации
Если ваша структура URL не содержит тегов %category%
, %tag%
, %author%
, необходимости в использовании этого метода оптимизации нет. Однако, если эти теги используются, то метод даст отличный эффект.
Тесты
В комментариях меня "провоцировали" провести тесты, чтобы увидеть, как такой метод, на самом деле, влияет на оптимизацию. Вот что я нашёл:
Согласно структуре URL /%category%/%postname%
, функция the_permalink()
(которая также является get_permalink()
, но без фильтров) генерирует 10 ссылок за 0.12 секунды. Тогда как при структуре URL, такой как, например, /%year%/%monthnum%/%day%/%postname%
, это занимает всего 0.02 секунды.
Я проводил измерения на своём компьютере, где для сравнения главная страница WordPress 3.0.1 с темой по умолчанию создаётся за 1.3 секунды.
Таким образом, если наш URL содержит %category%
и на странице отображается 50 уникальных (неповторяющихся) ссылок, это займёт дополнительно 0.6 секунды (0.12*5=0.6) для генерации этой страницы, что почти полсекунды.
Следует отметить (я не знал этого прежде), что после генерации ссылки один раз WordPress кэширует её, и когда the_permalink()
вызывается снова для того же поста, ссылка генерируется за доли секунды. То есть так:
// получить ссылку для поста с ID 25
the_permalink(25); // время 0.012
// получить ссылку снова
the_permalink(25); // время, примерно, 0.0001
Кажется, что я сказал всё, что хотел, всё остальное можно легко уточнить в комментариях.