Правка фронтенда в ocStore OcStore(OpenCart) 3.0.2. Переделка под свои нужды.
Всем, привет.
Здесь мне бы хотелось говорить о трудностях, с которыми я сталкиваюсь по сабжу. Может быть в дальнейшем кому-то эта инфа пригодится. Опыта работы с OpetCart у меня нет, тем более 3-й версии, но поступил заказ. Что ж, придётся ковыряться. Имеется макет в фотошопе, вообще ни разу не напоминающий диз CMS-ки из коробки. Начал стилизовать блоки в twig-файлах по-своему, дошёл до корзины и сразу сталкнулся со следующей проблемой. Мне НЕ нужна к корзине надпись вида `Товаров: 0 (0.00р.)`, а нужно получить лишь количество товаров. Ок, - подумал я - В бэкенд не полезу, вдруг такая строчка целиком ещё пригодится или сломаю что-нибудь не дай Бог. 1. Полез в файл `domains/mysite/catalog/view/javascript/common.js` Нашёл там объект `cart` со своими методами типа `add`, `update` etc. с ajax-ом и колбэками. 2. В колбэках нахожу строку:
$('#cart > button').html('<span id="cart-total"><i class="fa fa-shopping-cart"></i> ' + json['total'] + '</span>');
Вывожу в консоль json['total'], ОНО! 3. В этом же файле создаю глобально метод:
var getAmount = function (total) {
var regex = /\s+/,
amount = total.split(regex)[1];
return amount;
}
..а в строке колбэка функций объекта `cart` (см. выше) вызываю его: getAmount(json['total']). 4. Аллилуйя! Всё работает. Едем дальше. 1. Заходим на сайте в карточку товара, добавляем товар в корзину и упс - возвращается необработанная строка json['total']. 2. Инспектируем getAmount(), добавляя в него `console.log('getAmount method called')` - хренушки (( Метод не вызывается. 3. Ок, инспектируем кнопу `Купить` в карточке товара и находим событие на кнопке:
$('#button-cart').on('click', function() {...}
В файле common.js его, нет, но девтулс нам указывает на то, что он типа в index.php есть. Значит, событие возможно прописано в шаблоне twig. Ищем шаблон `product.twig` - Упс! Вот оно наше событие )) 5. В шаблоне `product.twig` снова вызываем наш новый метод `getAmount` и передаём в него json['total']. 6. Аллилуйя! Всё работает )) зы: прошу прощения, коллеги, если не в тот раздел запостил тему. Но сабж полезный имхо. Перенесите, если что. Принимаются замечания. Если что-то не будет получаться по сабжу, буду задавать здесь вопросы ) |
"трудна и ужасна жизнь насекомых" @Кто-то там ))
|
Цитата:
$_['text_items'] = 'Товаров %s';// (%s)'; |
Цитата:
Надо сначала доку почитать, чем сходу свои костыли подставлять. Мы лёгких путей не ищем :lol: Здесь надо поменять `catalog/language/ru-ru/common/cart.php` и здесь `catalog/language/ru-ru/checkout/cart.php` на $_['text_items'] = '%s'; Там по ходу php-функция sprintf() их обрабатывает. зы: почему карму повысить не могу? |
Если число только оставить, то да, первую переменную только и оставляем. Выводит да форматированием, и это и в методах добавления, и методах редактирования, и при запросе страницы делается, типа sprintf($this->language->get('text_items'), $this->cart->countProducts() ....
Есть контроллер, у него есть шаблон и локализация, последнюю и нужно править. |
Цитата:
|
Обнулить стили у кнопки Корзины получается, но не до конца. Убрал у неё все бутстраповские классы, которые подсасывает openCart, за исключением `.dropdown-toggle`. Прописал обнуление стилей в css вот так
После нажатия на кнопку она всё равно стилизуется как показано в скриншотах: ![]() ![]() Опытным путём установил, что происходит это тогда, когда я пытаюсь увеличить размер кнопки через width, height или padding. В чём может быть проблема? |
Проблема решена. С помощью box-shadow )))
|
Триви, ведь кеш работает, на время манипуляций его отключать надо.
|
Цитата:
Сейчас настал черёд стилизации карусели, тот ещё гимор я так понимаю. Главное свою не написать случайно )) А то я могу ))) |
Не получается сделать у слайдера background прозрачным. Я уже даже в шаблоне на всех тэгах поставил style="background: transparent;" и всё равно вокруг картинки белый фон :help:
зы: кэш отключён. |
А в реальности что на странице, что показывает отладчик?
|
Цитата:
Можно добавить в контроллер и шаблон шапки страниц (файлы common/header...): контроллер:
$template = $this->config->get('theme_default_directory'); //тема по умолчанию
$data['template'] = $template;
$data['last_time_style'] = filemtime(DIR_TEMPLATE.$template.'/stylesheet/stylesheet.min.css');
$data['last_time_script'] = filemtime(str_replace('theme/', '', DIR_TEMPLATE).'javascript/common.min.js');
а в шаблоне для файла стиля и js:
<link href="catalog/view/theme/{{template}}/stylesheet/stylesheet.min.css?{{last_time_style}}" rel="stylesheet">
<script src="catalog/view/javascript/common.min.js?{{last_time_script}}" type="text/javascript"></script>
тогда при изменениях в этих файлах браузер будет брать их новую версию. |
Цитата:
![]() Я так понимаю это для того, чтобы вьюпорт слайдера растянуть за счёт картинке. Бред какой-то. Так происходит с форматом jpg. А к png он тоже добавляет поля, но слава Богу transparent. Не проще бы было вьюпорт сделать равным ширине контейнера, а уж картинка чтобы была as it is. У меня в дизайне десктопа картинка должна быть по центру, а стрелочки по бокам с отступом откартинки порядка 100px; Можно ли как-то пофиксить загрузку картинок? |
Цитата:
Конечно же можно сделать, чтобы при сохранении для чего-то сохранялось так как есть. Но я не наблюдал, чтобы при сохранении фото менеджер добавлял поля, это делается только для эскизов указанных размеров. |
В админке оказывается есть настройка размеров контейнера. Выставил там ширину 600. Я хрен знает какому из 4-х контейнеров свайпера он добавляет это значение. В инспекторе не видно нифига.
Плюс для .swiper-container в стилях добавил строку max-width: 600px и всё заработало. В общем танец с бубном одним словом )) Не успел с этим разобраться и тут снова очередной геморрой. Открываю шаблон catalog/view/theme/mysite/template/extension/module/latest.twig для рекомендованных товаров, который выводится на главной странице, начинаю править - Изменений нет :cray: |
Значит он есть в кеше и берется из него. В админке, после правки - кеш тем "Обновить".
|
Цитата:
|
Цитата:
Обновлял, и даже установил отдельный модуль по чистке кэша. Правда он не удаляет модификаторы. Я пока не очень понимаю что это такое. ![]() ![]() |
Цитата:
|
Цитата:
Нашёл шаблон: `catalog/view/theme/soniya-shop/template/extension/module/featured.twig` Туплю жестоко. Думал взять опенкарт нахрапом, ан не получается. Надо сначала почитать что-то типа этого http://forum.opencart-russia.ru/thre...botchika.6107/ А то как слепой котёнок там брожу в нём наугад. |
Цитата:
|
Нужно вывести `select` во всех товарах в разделе Рекомендуем на главной странице.
1. Беру за основу для копирования кода контроллер `mysite\catalog\controller\product/product.php` (1.1) и шаблон к нему `mysite/catalog/view/theme/mysite/template/product/product.twig` (1.2) 2. Открываю контроллер нужного модуля `mysite/catalog/controller/extension/module/featured.php` (2.1) и шаблон к нему `mysite/catalog/view/theme/mysite/template/extension/module/featured.twig` (2.2) 3. Копирую в цикл файла 2.1, перебирающий товары, кусок кода из 1.1, отвечающий за этот option. Меняю `foreach ($this->model_catalog_product->getProductOptions($this->request->get['product_id']) as $option) {...}` на `foreach ($this->model_catalog_product->getProductOptions($product_id) as $option) {...}` Вот этот кусок:
$data['options'] = array();
foreach ($this->model_catalog_product->getProductOptions($product_id) as $option) {
$product_option_value_data = array();
foreach ($option['product_option_value'] as $option_value) {
if (!$option_value['subtract'] || ($option_value['quantity'] > 0)) {
if ((($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) && (float)$option_value['price']) {
$price = $this->currency->format($this->tax->calculate($option_value['price'], $product_info['tax_class_id'], $this->config->get('config_tax') ? 'P' : false), $this->session->data['currency']);
} else {
$price = false;
}
$product_option_value_data[] = array(
'product_option_value_id' => $option_value['product_option_value_id'],
'option_value_id' => $option_value['option_value_id'],
'name' => $option_value['name'],
'image' => $this->model_tool_image->resize($option_value['image'], 50, 50),
'price' => $price,
'price_prefix' => $option_value['price_prefix']
);
}
}
$data['options'][] = array(
'product_option_id' => $option['product_option_id'],
'product_option_value' => $product_option_value_data,
'option_id' => $option['option_id'],
'name' => $option['name'],
'type' => $option['type'],
'value' => $option['value'],
'required' => $option['required']
);
}
Далее копирую из шаблона 1.2 в шаблон 2.2 следующее:
{% if options %}
{% for option in options %}
{% if option.type == 'select' %}
<div class="form-group{% if option.required %} required {% endif %}">
<label class="control-label" for="input-option{{ option.product_option_id }}">{{ option.name }}</label>
<select name="option[{{ option.product_option_id }}]" id="input-option{{ option.product_option_id }}" class="form-control">
<option value="">{{ text_select }}</option>
{% for option_value in option.product_option_value %}
<option value="{{ option_value.product_option_value_id }}">{{ option_value.name }}
{% if option_value.price %}
({{ option_value.price_prefix }}{{ option_value.price }})
{% endif %} </option>
{% endfor %}
</select>
</div>
{% endif %}
В результате в шаблон передаётся массив данных последнего товара в цикле и всем товарам прописывыется этот селект. Сделал проверку print_r($data); Да, так и есть. Т.о. придётся городить многомерные массивы на PHP, чтобы в product_id запихать ещё и соответствующий ему опшен? По сути уже в модуль лезу и это настораживает. В ту ли сторону я вообще начал ковырять? Или есть что-то уже написанное и не нужно вовсе лезть в эти дебри? |
Ну вот я перебрал только что в массиве массива в контроллере все опшенсы, затем засунул их как массив $options в массив $data. Получилось вот так:
Array
(
[products] => Array
(
[3] => Array
(
[product_id] => 30
[thumb] => https://mysite/image/cache/catalog/demo/canon_eos_5d_1-200x200.jpg
[name] => Canon EOS 5D
[model] => Product 3
[description] =>
Canon's press material for the EOS 5D states that it 'defines (a) new D-SLR category', while we'r..
[price] => 50.00р.
[special] => 80.00р.
[tax] =>
[rating] =>
[options] => Array
(
[product_option_id] => 226
[product_option_value] => Array
(
[0] => Array
(
[product_option_value_id] => 15
[option_value_id] => 39
[name] => Red
[image] =>
[price] =>
[price_prefix] => +
)
[1] => Array
(
[product_option_value_id] => 17
[option_value_id] => 41
[name] => Green
[image] =>
[price] => 10.00р.
[price_prefix] => +
)
[2] => Array
(
[product_option_value_id] => 16
[option_value_id] => 42
[name] => Yellow
[image] =>
[price] => 50.00р.
[price_prefix] => +
)
)
[option_id] => 5
[name] => Select
[type] => select
[value] =>
[required] => 1
)
[href] => https://soniya-shop/index.php?route=product/product&product_id=30
)
)
)
Далее в шаблоне в цикле по массиву `products` обращаюсь к массиву options вот так:
{% for product in products %}
{% if product.options %}
{% for option in product.options %}
{% if option.type == 'select' %}
...
Ошибок нет, но нифига не работает. |
Цитата:
|
{% for product in products %}
{% if product.options %} как, если [products] => Array ( [3] => Array ? На чем тренировки производятся, на удаленном сервере? Ставьте локальный сервер и тренируйтесь на нем, делая вывод в браузер данных дабы проверить себя, и прочее, что на реальном сервере конечно же делать не стоит. Для изучения twig можно создать виртуальный хост только из него. |
Цитата:
{% for product in products %}
Все эти {{ product.name }} и прочие в шаблоне выводятся, но когда дело доходит до того, чтобы пролистать вложенный в products массив options, то ничего не получается. Цитата:
|
Цитата:
$arr = [
3 => [
12,
45
]
];
цикл for выведет Array. И только {% for itm in arr[3] %} отобразит его содержимое. Так что либо цикл в цикле, либо готовить структуру необходимую перед передачей в шаблон. |
Триви, просто проверяйте тип:
{% for product in products %}
{% if product is iterable %}
{% for item in product %}
{{ item }}
{% endfor %}
{% else %}
{{ product }}
{% endif %}
{% endfor %}
Если охота проверять ключи, то конечно не таким образом if item.name, ибо это проверка его значения на true/false. Непосредственно перебрать ключи/значения вы не сможете так как у вас массив вложенный, а если его структура будет такой (сокращено):
$arr = [
'product_id' => 30,
'thumb' => 'https://mysite/image/cache/catalog/demo/canon_eos_5d_1-200x200.jpg',
'name' => 'Canon EOS 5D',
'model' => 'Product 3',
'description' => 'Canon press material for the EOS 5D',
'price' => '50.00р',
'special' => '80.00р',
'options' => [
'product_option_id' => 226,
'product_option_value' => [
[
'product_option_value_id' => 15,
'option_value_id' => 39,
'name' => 'Red'
],
[
'product_option_value_id' => 17,
'option_value_id' => 41,
'name' => 'Green'
],
[
'product_option_value_id' => 16,
'option_value_id' => 42,
'name' => 'Yellow'
]
],
'option_id' => 5,
'name' => 'Select',
'type' => 'select',
'required' => 1
],
'href' => 'https://soniya-shop/index.php?route=product/product&product_id=30'
];
то можно проверять текущий ключ (для примера проверяется и ключ 'href', чтобы не экранировать &):
<ul>
{% for key, val in arr %}
{% if key == 'options' %}
<ul>
{% for k, v in val %}
{% if k == 'product_option_value' %}
<ul>
<li>{{ v }} опять вложение, цикл</li>
</ul>
{% else %}
<li>{{ v }}</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<li>{% if key == 'href' %}{{ val|raw }}{% else %}{{ val }}{% endif %}</li>
{% endif %}
{% endfor %}
</ul>
Хотя зная структуру массива проще проверять является ли значение итерируемым и соответственно поступать. Проверка ключа потребуется, например, если каждый из них будет иметь различный вывод. |
Создайте домен для twig, скопировав в него twig или composer и загрузить. Создать индексный файла, в котором:
include_once('library/template/Twig/Autoloader.php');
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('templates');
$twig = new Twig_Environment($loader); //без кеширования
//определяем что-то для передачи в шаблон
echo $twig->render('имя файла шаблона', ['name_for_twig' => $data]);
И файл шаблона. Будет легче что-то проверить. |
Победил я таки вывод опций в списке товаров. Добавил ещё вывод необходимых атрибутов (характеристик). С ними проще было. Решение заслуживает отдельной статьи, а времени как обычно нет.
|
В Opencart иногда встречается небольшое представление в контроллерах.
Сейчас снова попалось:
$children_data[] = array(
'name' => $child['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
'href' => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])
);
Меня например бесило, что количество товаров в детях категории прыгало на другую строчку. Особенно если количество равно нулю. Пришлось в контроллере в этом месте вставить ` `. По-хорошему надо переписать по человечески, но как обычно время поджимает, да и никто этого всё равно не оценит )) |
Цитата:
|
Цитата:
У меня такой вопрос. Мне нужно будет реализовать следующий функционал: - Сделать список подарков. Я так понимаю, это просто товары, помещённые в раздел `Подарки`. - Если сумма в корзине достигает определённого значения, то предлагать на выбор эти подарки. Я полагаю, что такие модули уже давно кем-то написаны. А то я буду несколько месяцев его писать, а мне проект сдавать уже через месяц. Есть такой опыт? Не подскажешь(-те) какой модуль выбрать? И ещё.. сторонние модули не переписывают штатные контроллеры и модели? Ну и в js желательно чтобы тоже не лезли, а подключали свой. |
Цитата:
Если вы читали о модификаторах, значит должны знать, что можно найти строку кода в исходнике, заменить ее другим кодом, который и будет выполняться. А можно указать заменить строки после найденной, вставить после найденной. Допустим вы заменили какую либо строку непосредственно в исходнике. Затем вы установили некое расширение, которое при этом будет модифицировать в том числе и код исходника, который вы изменили, и как раз касающийся строки которую вы изменили. Если требуется замена, то в зависимости от ситуации в лучшем случае будет отказ и расширение не добавиться, в худшем случае добавится и будут ошибки. Ну а если поиск будет до измененной строки с заменой после нее, то все ваши изменения будут вырезаны из исходника и не будут работать, а значит гарантированы ошибки уже вами заложенные. И это касается всего и js в том числе. Цитата:
Здесь же, с форума, выполнял заказ, когда заказчик не понимая назначения этой CMS взял ее для своего сайта, а она даже на 10% и то не подходит под его задачи. Вот в этом случае, дешевле для него было бы, это заблокировать весь ненужный хлам opencart, переписав начисто код двух контроллеров и шаблонов, ну и немного моделей, и новый js, чем разрабатывать стратегию и писать новый модуль, а им то нужно еще и из админки управлять. Но у него специфическая задача и ему никогда и не потребуется добавлять что-то новое, так что ничего не слетит у него. Так что тут уж не мне судить, что будет дальше у вас, вам виднее. |
Цитата:
Свяжусь с автором, попрошу поправить под третью версию. По-другому никак. Опыта написания модулей под оупенкарт, как вы понимаете, у мня нет. |
Снова в движке косяк.
В пустой дискрипшн категории добавляется `<p><br></p>`. Не знаю какой в этом тайный эротический смысл. Пришлось в шаблоне прописать:
{% if description and description != "<p><br></p>" %}
<div class="col-sm-10">{{ description }}</div>
{% endif %}</div>
Хотя так и чешутся руки сделать в php данную проверку. |
Цитата:
|
Для редактирования текста Opencart использует редактор Summernote.
Хотел немножко стили под себя подправить, иду сюда admin/view/javascript/summernote/summernote.css Открываю стили, а они сборщиком минифицированы. Вот на хрена так спрашивается делать, блин? |
Цитата:
|
| Часовой пояс GMT +3, время: 06:57. |