Антон Ким

Личный опыт работы с OpenCart 3
Все заметкиantonkim@antonkim.ru

Как минифицировать HTML в OpenCart

Для более быстрой загрузки страниц.

Как сделать

  1. Идём в system/library/response.php.
  1. Находим код (у меня он на 108 строке):
public function output() {
	if ($this->output) {
		$output = $this->level ? $this->compress($this->output, $this->level) : $this->output;
		
		if (!headers_sent()) {
			foreach ($this->headers as $header) {
				header($header, true);
			}
		}
		
		echo $output;
	}
}
  1. Заменяем на:
public function output() {
 
if ($this->output) {
    $this->output = preg_replace("/(\n)+/", "\n", $this->output);
    $this->output = preg_replace("/\r\n+/", "\n", $this->output);
    $this->output = preg_replace("/\n(\t)+/", "\n", $this->output);
    $this->output = preg_replace("/\n(\ )+/", "\n", $this->output);
    $this->output = preg_replace("/\>(\n)+</", '><', $this->output);
    $this->output = preg_replace("/\>\r\n</", '><', $this->output);
}

if ($this->output) {
	$output = $this->level ? $this->compress($this->output, $this->level) : $this->output;
	
	if (!headers_sent()) {
		foreach ($this->headers as $header) {
			header($header, true);
		}
	}
	
	echo $output;
}
}
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.

Как сделать сортировку атрибутов по порядку сортировки в OpenCart

Потратил кучу времени на поиск решения, а в итоге оно оказалось до смешного простым.

В чём проблема

Вот мы создали группу атрибутов. Затем создали атрибуты, привязали к группе атрибутов, задали порядок сортировки. На сайте всё отображается нормально — согласно порядку сортировки. Но вот в админке сортировка идёт по названиям, и это очень сбивает.

Как исправить

  1. Идём в admin/model/catalog/attribute.php.
  1. Находим код (у меня он на 53 строчке):
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
	$sql .= " ORDER BY " . $data['sort'];
} else {
	$sql .= " ORDER BY attribute_group, ad.name";
}
  1. Видоизменяем последнюю строку:
$sql .= " ORDER BY attribute_group, a.sort_order, ad.name";
  1. То есть, по умолчанию, в карточке товара в админке стоит сортировка по названию. Мы же сделали по порядку сортировки, а затем по названию.
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.

Автогенерация тайтла в OpenCart

Чтобы получилось вот так:

При этом, чтобы иметь возможность отдельно редактировать сам тайтл.

Как сделать

  1. Идём в admin/view/template/catalog/product_form.twig.
  1. Находим код (у меня на 67 строчке):
<input type="text" name="product_description[{{ language.language_id }}][meta_title]" value="{{ product_description[language.language_id] ? product_description[language.language_id].meta_title }}" placeholder="{{ entry_meta_title }}" id="input-meta-title{{ language.language_id }}" class="form-control" />
  1. После него вставляем:
<script type="text/javascript">
$(function() {
  var $name_input = $("input[name='product_description[{{ language.language_id }}][name]']");
  var $meta_title = $("input[name='product_description[{{ language.language_id }}][meta_title]']");

  $name_input.keyup(function() {
  $meta_title.val($name_input.val());
  });
});
</script>
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.
  1. Можно пойти дальше. Например, чтобы после названия было «купить в „название“».
  1. Видоизменяем одну строку:
$meta_title.val($name_input.val() + 'Тут какой-то текст');
  1. Готово — 2.
  1. Ту же самую процедуру можно провернуть и с категориями.


Спасибо за помощь Ярославу Усенко.

Как сделать сортировку товаров по наличию в OpenCart

И в магазине, и в админке.

В чём проблема

По умолчанию, все товары в категориях, страницах производителей, поиске — сортируются по названиям в алфавитном порядке. И даже те товары, которых нет в наличии, могут отображаться в начале списка. А когда таких товаров много — это становится проблемой.

Как решить

  1. Идём в catalog/model/catalog/product.php.
  1. Находим код (у меня он на 168 строчке):
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
	if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
		$sql .= " ORDER BY LCASE(" . $data['sort'] . ")";
	} elseif ($data['sort'] == 'p.price') {
		$sql .= " ORDER BY (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
	} else {
		$sql .= " ORDER BY " . $data['sort'];
	}
} else {
	$sql .= " ORDER BY p.sort_order";
}
  1. Заменяем его на:
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
    if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
        $sql .= " ORDER BY p.stock_status_id DESC, LCASE(" . $data['sort'] . ")";
    } elseif ($data['sort'] == 'p.price') {
        $sql .= " ORDER BY p.stock_status_id DESC, (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
    } else {
        $sql .= " ORDER BY p.stock_status_id DESC, " . $data['sort'];
    }
} else {
    $sql .= " ORDER BY p.stock_status_id DESC, p.sort_order";
}
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово. Теперь товары будут сортироваться по наличию. Товаров, которых нет в наличии, будут отображаться в конце списка.
  1. Можно сортировать и по количеству, а уже затем по статусу. Для этого заменяем на:
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
    if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
        $sql .= " ORDER BY p.quantity DESC, p.stock_status_id DESC, LCASE(" . $data['sort'] . ")";
    } elseif ($data['sort'] == 'p.price') {
        $sql .= " ORDER BY p.quantity DESC, p.stock_status_id DESC, (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
    } else {
        $sql .= " ORDER BY p.quantity DESC, p.stock_status_id DESC, " . $data['sort'];
    }
} else {
    $sql .= " ORDER BY p.quantity DESC, p.stock_status_id DESC, p.sort_order";
}
  1. Можно использовать разные комбинации. Можно сортировать и по стоимости, и по рейтингу, и по дате добавления. Нужно лишь подменить значения в коде выше. Вот они:
$sort_data = array(
    'pd.name',
    'p.model',
    'p.quantity',
    'p.price',
    'rating',
    'p.sort_order',
    'p.date_added'
);

Как это сделать в админке

  1. Идём в admin/mode/catalog/product.php
  1. Делаем тоже самое, что и наверху.
  1. Готово.

По теме

Сортировка данных в SQL (ORDER BY).

Как подключить LazyLoad в OpenCart

На страницы товаров, в категориях, результаты поиска, страницы производителей.

В чём проблема

Ленивая загрузка изображений здорово помогает при взаимодействии с сайтом. Как минимум, он начинает загружаться значительно быстрее.

Как сделать

  1. Скачать lazyload.min.js.
  1. Как альтернатива его можно подключить ссылкой:
<script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@15.1.1/dist/lazyload.min.js"></script>
  1. Залить файл в catalog/view/javascript/. Ну или куда удобно.
  1. Подключить в header.twig в своей теме.
  1. В footer.twig, перед закрывающим тегом body, вставить:
<script>
var lazyLoadInstance = new LazyLoad({
    elements_selector: ".lazy"
});
</script>
  1. Теперь идём в catalog/view/тема/product/category.twig.
  1. И к каждому тегу img добавляем класс lazy, а вместо src — data-src. Вот так это будет выглядеть:
<img class="lazy" data-src="ссылка на изображение" alt="">
  1. Тоже самое теперь нужно проделать в файлах product.twig, search.twig, manufacturer_info.twig.
  1. Всё сохраняем, обновляем кэш и вот это всё.
  1. Готово.
  1. Для работы скрипта нужна подключенная библиотека jquery.
  1. У этого скрипта куча настроек и возможностей — всё можно посмотреть на гитхабе.

Как исправить баг с адаптивностью в админке OpenCart

И начать нормально жить.

В чём проблема

Не знаю как у других, но когда я заходил в админку, было вот так:

Приходилось включать десктоп режим, что не вызывало восторга.

Потратил много времени прежде чем найти решение. А оно до смешного — простое.

Как исправить

  1. Перейти в admin/system/tweak.ocmod.xml.
  1. Найти код (у меня он находится на 13 строчке):
<operation>
	<search><![CDATA[
	{% for link in links %}
	]]></search>
	<add position="before"><![CDATA[
	<script type="text/javascript" src="view/javascript/jquery/translit.js"></script>

	<style>
	#column-left {width: 260px !important;}
	#column-left + #content {margin-left: 260px !important;}
	.bimage {margin:0;}
	</style>
	]]></add>
</operation>
  1. Удалить из него вот эту часть:
<style>
#column-left {width: 260px !important;}
#column-left + #content {margin-left: 260px !important;}
.bimage {margin:0;}
</style>
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.
  1. Вот что на выходе:
Красота

Как сделать исходный код в редакторе товаров OpenCart с нормальной разметкой

Двумя строчками кода.

В чём проблема

Когда вы заходите в исходный код описания, то всё выглядит вот так:

Всё в одну строку, с прокруткой, без нормальной разметки

Как исправить

  1. Переходим в admin/view/javascript/summernote/opencart.js.
  1. Найти код (у меня он находится на 10 строке):
$(element).summernote({
    lang: $(this).attr('data-lang'),
    disableDragAndDrop: true,
    height: 500,
    emptyPara: '',
    codemirror: { // codemirror options
        mode: 'text/html',
        htmlMode: true,
        lineNumbers: true,
        theme: 'monokai'
	},
  1. После строки lineNumbers вставляем:
lineWrapping: true,
  • Это уберёт прокрутку и разметка начнёт переносится на новые строки.
  1. После строки emptyPara вставляем:
prettifyHtml: true,
  • Это приведёт кашу с разметкой в человеческий вид.
  1. Сохраняем, обновляем кэш.
  1. Готово.
  1. Вот так это будет выглядеть на выходе:
Красота

Как отключить форматирование при копировании в OpenCart

И не страдать.

В чём проблема

Когда вы хотите откуда-то скопировать текст, он копирует его целиком — вместе со стилями того источника.

Есть два решения.

Первое — копировать и вставлять не через Ctrl + V, а через Ctrl + Shift + V.

Второе — отключить форматирование при копировании вообще.

Как это сделать

  1. Переходим в admin/view/javascript/summernote/opencart.js.
  1. Находим код (у меня он находится на 10 строке):
$(element).summernote({
    lang: $(this).attr('data-lang'),
    disableDragAndDrop: true,
    height: 400,
    emptyPara: '',
    codemirror: { // codemirror options
        mode: 'text/html',
        htmlMode: true,
        lineNumbers: true,
        theme: 'monokai'
    },
  1. После него вставляем:
callbacks: {
    onPaste: function(e) {
        var bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
        e.preventDefault();
        setTimeout(function() {
            document.execCommand('insertText', false, bufferText);
            }, 10);
        }
},
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.

Как по умолчанию сделать видео адаптивным в OpenCart

Не залезая в исходный код.

В чём проблема

Когда вы вставляете видео с ютуба (кнопка «Видео») оно имеет размеры 640х360. Чтобы сделать его адаптивным, приходится лезть в код и дополнять его. Это неудобно и неприятно.

Как автоматизировать

У меня по умолчанию установлен редактор summernote, поэтому инструкция для него.

  1. Перейти в admin/view/javascript/summernote/summernote.js.
  1. Найти код (у меня он находится на 6463 строке):
$video.addClass('note-video-clip');

return $video[0];
  1. Заменить его на:
var $embed;
var $embed = $('<div>').addClass('embed-responsive').addClass('embed-responsive-16by9');

$video.addClass('note-video-clip').addClass('embed-responsive-item');
$video.appendTo($embed);

return $embed[0];
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Теперь при добавлении видео оно сразу будет адаптивным.
  1. Это не всё. Теперь добавим возможность включать полноэкранный режим.
  1. В том же файле найти код (у меня он находится на 6418 строке):
var $video;
if (ytMatch && ytMatch[1].length === 11) {
    var youtubeId = ytMatch[1];
    $video = $('<iframe>')
        .attr('frameborder', 0)
        .attr('src', '//www.youtube.com/embed/' + youtubeId)
        .attr('width', '640').attr('height', '360');
  1. Добавляем после последнего .attr:
.attr('allowfullscreen', '');
  1. Сохраняем, обновляем кэш и вот это всё.
  1. Готово.