17 Март 2012

All in One Seo Pack и MaxCache - решение проблемы с title

Приветствую вас, уважаемый читатель!

Данная публикация посвящена блоггерам, использующим для ускорения движка WordPress кеширующий плагин MaxCache.

Я, используя MaxCache на данном блоге, неожиданно столкнулся со следующей проблемой: неправильно отображается title, сформированный плагином «All in One Seo Pack» на закешированной при помощи MaxCache странице.

Самое забавное, что я, с того момента как поставил MaxCache, не замечал проблемы; ведь после публикации я наблюдал некешированную страницу, на которой тайтл отображался именно так, как я задал в настройках All in One Seo Pack.

Каково же было мое удивление, когда я заметил, что в кеш попадает страница совсем с другим title! Оказывается, закешированная страница имеет тайтл, сформированный по умолчанию стандартной функцией WordPress wp_title().

Функция wp_title(), по умолчанию, в качестве title поста использует его заголовок. А с точки зрения SEO, часто возникает задача сделать тайтл и заголовок поста разными. Да и вообще,я для всех своих постов title указывал в ручную плагином All in One Seo Pack, жалко свою работу становится.

Решил я бороться с возникшей проблемой.

Что самое интересное, одновременно со мной над данной проблемой задумался Tod и, буквально вчера, опубликовал пост с вариантом решения. Мне описанное там решение не подошло, т. к. в посте речь идет о плагине All Meta, которым я не пользуюсь. И, на сколько я понял, Tod предлагает решение, которое приведет все к тому же выводу названия постов в title.

Причина возникшей проблемы

Как написал Максим, в конце страницы описания плагина MaxCache, проблема возможна из-за буферизации вывода. Думаю, так оно и есть, хотя более детально суть проблемы я не установил.

Description и keywords, подготовленные плагином All in One Seo Pack, на закешированную страницу попадали исправно. Проблема возникала только с title.

Дело в том, что description и keywords выводятся хуком wp_head. Данный вопрос я наглядно осветил в видеоуроке по настройке раздела head в WordPress.

Получается, что в теме WordPress не нужно указывать тегов description и keywords, они появятся автоматически после выполнения функции wp_head. И все это дело без проблем работает с MaxCache.

А вот с title другая ситуация. Как я показывал все в том же видеоуроке, нам обязательно нужно поставить хотя бы пустые теги <title></title>, т. к. указанное в All in One Seo Pack содержимое тайтла выводится именно путем замены тегов <title> темы.

Как же плагин осуществляет замену старого тайтла новым

Плагин All in One Seo Pack использует механизм буферизации. Буферизация позволяет, перед выводом HTML в браузер, отправить его в заданную функцию. Функция ищет в переданном буфере теги <title></title> и вырезает их вместе с содержимым. На место вырезанного куска встает тайтл, подготовленный плагином. Буферизация заканчивается и в браузер попадает HTML с подмененным тайтлом.

Убедитесь в этом, открыв на редактирование файл aioseop.class.php плагина All in One Seo Pack. Инструкция

ob_start(array($this, 'output_callback_for_title'));

(строка 106 для плагина версии 1.6.13.8) как раз включает буферизацию и передает HTML на обработку функции output_callback_for_title.

output_callback_for_title, посредством метода rewrite_title() как раз заменяет имеющийся в переданном HTML тайтл на тот, что был подготовлен плагином.

В функции rewrite_title() встречается куча условий, проверяющих какая именно страница загружается (страница поста, категорий, тегов и т. д.). Но каждый раз, по окончании проверок, выполняется метод replace_title(), который непосредственно вырезает старый тайтл и вставляет новый.

Так вот эта буферизация с MaxCache не работает нормально. Поэтому мы пойдем другим путем.

Решение проблемы

Мы будем брать тайтл, подготовленный All in One Seo Pack, и просто вставлять в HTML страницы функцией wp_head(), в полной аналогии с description и keywords.

Но, дабы у нас не было двух тайтлов одновременно, старый тайтл по умолчанию надо исключить из темы. Ведь теперь никакой замены старого тайтла на новый не будет, будет происходить просто вставка нового тайтла, подготовленного плагином.

Убрать старый тайтл очень просто: откройте на редактирование в текстовом редакторе файл header.php вашей темы и удалите оттуда строку вывода тайтла: <title></title>.

Вместо многоточия может стоять, например, функция вывода тайтла по умолчанию wp_title().

Прекрасно, идем дальше.

Теперь наше внимание приковываем к функции rewrite_title() (строка 654 файла aioseop.class.php). Как я говорил выше, данная функция в каждой из ветвей условного оператора «if» выполняет метод replace_title($header, $title), который непосредственно и осуществляет замену старого тайтла новым. На вход данный метод вторым аргументом получает значение нового тайтла.

Возьмем данное значение нового тайтла и выведем за пределы метода для дальнейшего использования. Для этого в конце функции rewrite_title(), перед оператором return $header (строка 820) укажем следующую команду:

$this->savedtitle = $title;

Данная команда создает свойство savedtitle у метода rewrite_title(), в которое помещается значение переменной $title, как раз содержащей значение нового тайтла.

Волею разработчика All in One Seo Pack, на протяжении метода rewrite_title(), новый тайтл не всегда находится в переменной $title. Есть две ветви оператора «if» в которых новый тайтл помещается в переменную $new_title и в $home_title. Дабы содержимое этих двух переменных также отправить в свойство savedtitle нужно приравнять их значения переменной $title:

  • под строкой 813 написать $title = $new_title;
  • под строкой 746 — $title = $home_title;

Следующий шаг — отправляемся в метод, выводящий description и keywords на страницы блога. В нем мы дополнительно выведем содержимое свойства savedtitle метода rewrite_title(), в котором хранится новый тайтл.

Description и keywords выводится методом wp_head() (строка 182). Данный метод осуществляет вывод подготовленных description и kewords в строке 342 операторами

if ($meta_string != null) {
    echo "$meta_string\n";
}

Прямо над оператором «if» в предыдущем листинге осуществим вызов метода rewrite_title() и отправим содержимое свойства savedtitle в выводимую переменную $meta_string.

Вот код, который осуществит задуманное:

$this->rewrite_title('');
$meta_string .= "\n<title>".$this->savedtitle."</title>\n";

Т. е. в подготовленную переменную $meta_string, содержащую description и keywords (а может быть и что-то еще), в конце будет добавлена строка нового тайтла.

Вообще говоря, проблема на этом решена.

Обращаю ваше внимание, уважаемый читатель, на тот факт, что в процессе редактирования файла aioseop.class.php строки будут смещаться и, возможно, не совпадать с нумерацией в статье. Также нужно понимать, что указанная нумерация строк актуальна только для версии плагина 1.6.13.8 — на момент написания статьи это свежайшая версия плагина All in One Seo Pack.

Вас вводят в ступор слова «метод», «свойство» и другие PHP-заморочки? — Тогда, специально для вас, я опубликовал базовый видеокурс по объектно-ориентированному программированию на PHP.

Желающие могут скачать исправленный файл aioseop.class.php и его нетронутую версию (41.3 кБ, *.zip).

P.S.: После того, как вы снесли из шаблона стандартный вывод тайтла, необходимо помнить, что по умолчанию тайтла на страницах у вас нет и он формируется только плагином All in One Seo Pack. На всякий случай приведу скрин настройки All in One Seo Pack, который я использую на своем блоге (с данными настройками тайтлы на всех страницах отображаются корректно):

Настройка All in One Seo Pack для моего блога

Скриншот кликабельный

С уважением, Андрей Морковин.