Свои теги h1 и title в OpenCart. Часть 1

Сегодня сделаем полезную с точки зрения SEO доработку OpenCart — добавим в административной части возможность самостоятельно определять тег <title> и тег <h1> для товаров и категорий, а также выводить их в пользовательской части. Я буду делать это правками в файлах ядра OpenCart для наглядности процесса, хотя крайне рекомендую делать это через vqmod или ocmod. Приступим!

Административная часть

Итак, мы будем исправлять все элементы MVC(L), т.к. у нас и форма редактирования товаров изменится, и в БД будем хранить информацию, языковые переменные будут и конечно Контроллер, который соберет это все вместе. Начнем с языковых переменных. Я советую делать правки в двух языковых версиях – основной (как правило, это russian или ukrainian) и «запасной» (english). Дело в том, что если нет перевода на выбранном в настройках  OpenCart языке, движок попытается найти его в english переводе, если и там не будет такой переменной, то уже выведет ошибку. Поэтому подстрахуемся.

Для товаров

Идем в admin/language/russian/catalog/product.php и добавляем в секции //Entry после $_['entry_meta_description'] = 'Мета-тег "Описание":';

$_['entry_meta_title'] = 'Тег "Title":';
$_['entry_meta_h1'] = 'Тег "H1":';

Для категорий

Идем в admin/language/russian/catalog/category.php и добавляем в секции //Entry после $_['entry_meta_description'] = 'Мета-тег "Описание":';

$_['entry_meta_title'] = 'Тег "Title":';
$_['entry_meta_h1'] = 'Тег "H1":';

Скажу, что такие имена переменных не совсем корректны, т.к. ни <h1> ни <title> по сути в HTML мета тегами не являются, это скорее дань сеошникам, т.к. все это они условно называют «мета тегами» в купе с <meta name='description' content='...'>, как весомые факторы внутренней поисковой оптимизации сайта.

Аналогичные правки делаем с английским переводом товарных переменных  admin/language/english/product.php и категорий admin/language/english/category.php

$_['entry_meta_title'] = 'Tag "Title":';
$_['entry_meta_h1'] = 'Tag "H1":';

На этом мы закончили с языковыми переменными. Перейдем к Модели. Первым делом, добавим в БД новые колонки meta_title и meta_h1. Сделаем это с помощью phpMyAdmin и небольшой команды. И тут нужно сделать очередную профессиональную оговорку. Дело в том, что через прямое обращение к БД через внешние средства нельзя предусмотреть различные префиксы для таблиц. В зависимости от вашей версии и редакции OpenCart (ocStore, OpenCart) этот префикс может отличаться от oc_ или вовсе отсутствовать. Обычно это либо oc_ либо префикс отсутствуюет вообще. Однако и в этом случае, если вы не сильны в SQL запросах, приведенный код может не сработать. Узнать какой у вас именно префикс можно в сonfig.php в корне установки OpenCart. За это отвечает строка define('DB_PREFIX', ''); в секции //DB. Как видите в моем примере там пусто, у вас же может быть define('DB_PREFIX', 'oc_'); или что-то еще. Теперь сам код SQL, который нужно ввести в консоль phpMyAdmin

ALTER TABLE product_description ADD meta_title varchar(255) NOT NULL;
ALTER TABLE product_description ADD meta_h1 varchar(255) NOT NULL;
ALTER TABLE category_description ADD meta_title varchar(255) NOT NULL;
ALTER TABLE category_description ADD meta_h1 varchar(255) NOT NULL

Можно сходить в таблицы и убедиться по структуре category_description, что все добавилось:

Аналогично и в product_description:

В принципе можно ограничить максимальное количество знаков в полях согласно рекомендациям Google или Яндекс — 72 знака, для этого в коде запроса к БД заменить varchar(255) на varchar(72), однако я не советую это делать, если вы используете какие-то массовые изменения на сайте. В этом случае часть значений может просто не записаться. Даже если <title> будет длиннее 72 знаков, Google или Яндекс его просто обрежут. Это не красиво, но будет давать эффект, в то время как пустое поле в БД как раз никакого SEO эффекта не окажет.

Так же можно воспользоваться функцией в Контроллере. Например, так для admin/controller/catalog/category.php после public function index() { добавляем:

$query = $this->db->query("DESC ".DB_PREFIX."category_description meta_title");
if (!$query->num_rows) {
$this->db->query("ALTER TABLE `" . DB_PREFIX . "category_description` ADD `meta_title` varchar(255) NOT NULL;");
}
$query = $this->db->query("DESC ".DB_PREFIX."category_description meta_h1");
if (!$query->num_rows) {
$this->db->query("ALTER TABLE `" . DB_PREFIX . "category_description` ADD `meta_h1` varchar(255) NOT NULL;");
}

Этот метод работы с БД имеет как плюсы так и минусы. Плюсы в том, что у вас нет необходимости нарушать основы паттерна MVC(L) — не делать правок руками в БД, а работь через Контроллер или Модель. Следовательно, можно использовать константы PHP и избежать в т.ч. проблем с различными префиксами в БД.

А минус этого подхода стал причиной появления ocmod (в том числе). В OpenCart 1.5.x нет четко обозначенного метода установки модификаций при которых можно выполнять единоразово какие-то действия в БД, например добавление или изменение полей или структуры. Речь не про модули, которые имеют свои интерфейсы, а именно модификаторы интерфейса уже существующих элементов OpenCart, например административной панели. Единственный лайфхак, который доступен это цикл if, как это реализовано выше. Однако в этом случае мы обречены на постоянное выполнение этого цикла при каждом обращении к фунции, т.е. оптимизацией тут не пахнет.

Теперь можем приступить к редактированию Моделей. Нам нужно изменить блоки в функциях создания и редактирования категорий. Идем в admin/model/catalog/category.php ищем такие строки в фунции public function addCategory($data):

foreach ($data['category_description'] as $language_id => $value) {
 $this->db->query("INSERT INTO " . DB_PREFIX . "category_description SET category_id = '" . (int)$category_id . "', language_id = '" . (int)$language_id . "', name = '" . $this->db->escape($value['name']) . "', meta_keyword = '" . $this->db->escape($value['meta_keyword']) . "', meta_description = '" . $this->db->escape($value['meta_description']) . "', description = '" . $this->db->escape($value['description']) . "'");
 }

Заменяем на:

foreach ($data['category_description'] as $language_id => $value) {
 $this->db->query("INSERT INTO " . DB_PREFIX . "category_description SET category_id = '" . (int)$category_id . "', language_id = '" . (int)$language_id . "', name = '" . $this->db->escape($value['name']) . "', meta_keyword = '" . $this->db->escape($value['meta_keyword']) . "', meta_description = '" . $this->db->escape($value['meta_description']) . "', meta_h1 = '" . $this->db->escape($value['meta_h1']) . "', meta_title = '" . $this->db->escape($value['meta_title']) . "', description = '" . $this->db->escape($value['description']) . "'");
 }

Такие же правки делаем в функции public function editCategory($category_id, $data). Ищем:

foreach ($data['category_description'] as $language_id => $value) {
 $this->db->query("INSERT INTO " . DB_PREFIX . "category_description SET category_id = '" . (int)$category_id . "', language_id = '" . (int)$language_id . "', name = '" . $this->db->escape($value['name']) . "', meta_keyword = '" . $this->db->escape($value['meta_keyword']) . "', meta_description = '" . $this->db->escape($value['meta_description']) . "', description = '" . $this->db->escape($value['description']) . "'");
 }

Заменяем на:

foreach ($data['category_description'] as $language_id => $value) {
 $this->db->query("INSERT INTO " . DB_PREFIX . "category_description SET category_id = '" . (int)$category_id . "', language_id = '" . (int)$language_id . "', name = '" . $this->db->escape($value['name']) . "', meta_keyword = '" . $this->db->escape($value['meta_keyword']) . "', meta_description = '" . $this->db->escape($value['meta_description']) . "', meta_h1 = '" . $this->db->escape($value['meta_h1']) . "', meta_title = '" . $this->db->escape($value['meta_title']) . "', description = '" . $this->db->escape($value['description']) . "'");
 }

Дальше, в коде:

foreach ($query->rows as $result) {
 $category_description_data[$result['language_id']] = array(
 'name' => $result['name'],
 'meta_keyword' => $result['meta_keyword'],
 'meta_description' => $result['meta_description'],
 'description' => $result['description']
 );
 }

Меняем на:

foreach ($query->rows as $result) {
 $category_description_data[$result['language_id']] = array(
 'name' => $result['name'],
 'meta_keyword' => $result['meta_keyword'],
 'meta_h1' => $result['meta_h1'],
 'meta_title' => $result['meta_title'],
 'meta_description' => $result['meta_description'],
 'description' => $result['description']
 );
 }

Все, с Моделью мы разобрались. Приступим к Контроллеру и закончим Представлением.

Идем в admin/controller/catalog/category.php и вставим там языковые перменные для новых полей Представления после $this->data['entry_meta_description'] = $this->language->get('entry_meta_description');

 $this->data['entry_meta_title'] = $this->language->get('entry_meta_title');
 $this->data['entry_meta_h1'] = $this->language->get('entry_meta_h1');

Закончили с Контроллером и перейдем к последнему пункту административной части — Представлению, которое отвечает за форму редактирования конкретной категории admin/view/template/catalog/category_form.tpl

Мне нравится, чтобы поля редактирования title и h1 находились сразу под под полем для Названия. Поэтому после этого кода

<tr>
 <td><span class="required">*</span> <?php echo $entry_name; ?></td>
 <td><input type="text" name="category_description[<?php echo $language['language_id']; ?>][name]" size="100" value="<?php echo isset($category_description[$language['language_id']]) ? $category_description[$language['language_id']]['name'] : ''; ?>" />
 <?php if (isset($error_name[$language['language_id']])) { ?>
 <span class="error"><?php echo $error_name[$language['language_id']]; ?></span>
 <?php } ?></td>
 </tr>

добавляем

 <tr>
 <td><?php echo $entry_meta_title; ?></td>
 <td><input type="text" name="category_description[<?php echo $language['language_id']; ?>][meta_title]" size="100" value="<?php echo isset($category_description[$language['language_id']]) ? $category_description[$language['language_id']]['meta_title'] : ''?>" /></td>
 </tr>
 <tr>
 <td><?php echo $entry_meta_h1; ?></td>
 <td><input type="text" name="category_description[<?php echo $language['language_id']; ?>][meta_h1]" size="100" value="<?php echo isset($category_description[$language['language_id']]) ? $category_description[$language['language_id']]['meta_h1'] : ''?>" /></td>
 </tr>

Давайте посмотрим, что у нас получилось

Если вы все сделали правильно, но так и не увидели результатов труда, почистите системный кеш и кеш vqmod в /vqmod/vqcache и /system/cache

Во второй части напишем пользовательскую часть.

Игорь Чишкала

Директор по технологиям в SoftForge. Люблю ИТ, пишу технические статьи в этом блоге или для сайта фриланс-биржи Upwork. Кодю на PHP с использованием фреймворков Laravel или Symfony.

3 Комментариев

  1. А для карточки товара достаточно только:
    Идем в admin/language/russian/catalog/product.php и добавляем в секции //Entry после $_[‘entry_meta_description’] = ‘Мета-тег «Описание»:’;

    $_[‘entry_meta_title’] = ‘Тег «Title»:’;
    $_[‘entry_meta_h1’] = ‘Тег «H1»:’;

    и создать таблицы в БД
    ??

    • Катерина, конечно нет. Все указанные действия практически, на 99% аналогичны для карточки товаров. Следовательно их ВСЕ нужно выполнить, подразумевая замену category на product. В логике OpenCart, то что касается модели и контроллера, категория и товар очень схожи.
      Я не ставил за цель написать пошаговую инструкцию, а скорее дать поле для фантазии. Если вы знаете немного PHP и метод аналогии, у вас все получится :)

      P.S. Задавайте вопросы, если застрянете.

Добавить комментарий

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