Оптимізація продуктивності 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 , причому відбувається це в якомусь хаотичному порядку. начебто, від того публікується матеріал до або після запису першої чернетки. Так, це й не важливо.
Таким чином, щоб постійно не генерувати посилання нам потрібно:
При публікації/оновленні запису в полі guid таблиці wp_posts записувати постійне посилання на статтю
- Під час використання посилання у шаблоні 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 .
До речі, у моїх функціях виводу: коментарях мені пригадали , що функція не чутлива до пермалинок
Для робочих сайтів, де поля guid вже визначені “неправильно”
Якщо сайт вже робітник і в ньому вже чимало записів, постійні посилання яких записані “неправильно” в полі guid, то для таких випадків я зробив плагін на перезапис (ремонт) поля guid:
Завантажити плагін

Встановлюється плагін як завжди: копіюємо файл з архіву 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
Начебто все сказав, що хотів, все інше можна легко прояснити в коментарях