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

# Оптимизация производительности 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

Кажется, что я сказал всё, что хотел, всё остальное можно легко уточнить в комментариях.

Leave a Reply

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