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

OpenCart
5 мин. на чтение

Сегодня сделаем полезную с точки зрения 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.
Оцените автора
Авторский блог Игоря Чишкалы
Добавить комментарий для Artem Отменить ответ

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

  1. Катерина

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

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

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

    Ответить
    1. Игорь Чишкала автор

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

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

      Ответить
  2. Artem

    А подойдет эта инструкция для opencart шаблона GlobeHTM версия 3.0.2.0?

    Ответить
  3. Artem

    Подойдет инструкция к шаблону Globehtm Opencart 3.0.2.0?

    Ответить
  4. Алекс

    Странно, что поля эти есть в OpenCart 1.5, но их нужно дорабатывать. Хорошо, что в oc 2 проблема решена.

    Ответить
    1. Ihor Chyshkala

      Эти поля по-умолчанию есть только в русской сборке ocStore. В чистом OpenCart их нет ни в какой версии :)

      Ответить
  5. Богдан

    Добрый день!
    Спасибо большое за статью.
    Подскажите, пожалуйста, как сделать данные манипуляции с помощью OCMOD?

    Заранее благодарю!

    Ответить
    1. Ihor Chyshkala

      Подобные модули и с OCMOD есть на opencartforum.com, бесплатно :)

      Ответить