Правка фронтенда в 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, время: 21:14. |