вторник, 5 сентября 2017 г.

Учимся писать полноценный модуль для Opencart 2.3

Учимся писать полноценный модуль для Opencart 2.3

В прошлый раз мы сделали мод для системы Opencart. Однако, в Опенкарте есть моды, а есть модули. Отличие такое: мод позволяет только изменить что-то в уже существующем материале; модуль – создаёт (добавляет) новый материал.

Понадобилось создать для одного магазина на Opencart новую систему формирования цены доставки. Новая система почти не отличается от "фиксированной цены", которая есть в opencart по умолчанию. Только к фиксированной цене нужно прибавлять ещё некоторую фиксированную сумму за каждую позицию (грузо-место).

Можно добавить такую функцию напрямую в дефолтный модуль "фиксированная стоимость", или сделать мод, как было описано в прошлой статье. Но в этом случае нельзя будет использовать оригинальный модуль – а он может понадобиться.

Отличный повод потренироваться – напишем (вернее, перепишем) свой модуль!

Большой плюс в том, что разбираться досконально в структурах и правилах модулей Opencart пока не нужно. Мы просто возьмём оригинальный модуль "фиксированная стоимость доставки" (его внутреннее имя в системе Опенкарта - flat, в extensions-shipping), переименуем его и подправим для себя.

Модули в Opencart состоят из набора файлов, лежащих в нескольких каталогах системы. Модули всегда лежат в каталогах extension. Языковые словари – всегда в language (без верхней папки extension).
Логика достаточно простая:
admin ->
   controller -> extension -> имя_модуля.php 
здесь лежат обработчики данных из админки
language -> en-gb -> имя_модуля.php
здесь словарь (англ. – en-gb) для админки
view -> extension -> имя_модуля.tpl
здесь шаблон для админки (генератор html-страницы)
model -> extension -> имя_модуля.tpl
работа с БД
И та же логика для catalog. Всё достаточно просто.

Скачаем или достанем из архива с Opencart файлы модуля flat по указанным путям. В нашем случае нет файлов модуля в секции model в admin, и controller в catalog.
Переименуем все файлы будущего модуля: из flat в новое имя. Имя лучше выбирать без подчёркиваний, пробелов и дефисов. Я назвал модуль fixed1stplus.
Начнём правку с файла в admin-controller-extension-fixed1stplus.php
Важная для нас строка: class ControllerExtensionShippingFlat extends ... . Вместо Flat нужно вставить имя нашего модуля. Это его код в системе, и все переменные, принадлежащие этому модулю, будут начинаться с этого кода. Получится так:
class ControllerExtensionShippingFixed1stplus.
Система не любит подчёркивания в названии, вариант ControllerExtensionShippingFixed_1st_plus не сработает. Поэтому и файлы лучше называть без подчёркиваний, во избежание путаницы.
Имя, соответственно, заменяем во всех файлах нашего нового модуля, где есть строка class ControllerExtensionShippingFlat.
А дальше делаем автозамену во всех файлах: грубо и сурово автоматически меняем flat на наше fixed1stplus.

Новый модуль уже готов. Если теперь загрузить его на сайт, он появится в списке как отдельный модуль. Правда, называться будет старым именем и делать то же, что и старый модуль :) Правим дальше:
> название модуля для админки меняем в файле admin - language - нужный код языка
> названия, видимые при оформлении заказа пользователями: в catalog - language 

Теперь функционал. В оригинальном модуле одна фиксированная сумма. А нам нужны: первоначальная сумма и сумма при добавлении грузо-места. Значит, нам нужно добавить переменную и запись в БД, где будет эта вторая сумма, поле ввода в админке, и доработать расчёт стоимости.
В admin-controller ищем блок
if (isset($this->request->post['fixed1stplus_cost'])) {
$data['fixed1stplus_cost'] = $this->request->post['fixed1stplus_cost'];
} else {
$data['fixed1stplus_cost'] = $this->config->get('fixed1stplus_cost');
}

Копируем его целиком, добавляем после первого. Переименовываем переменную. Получается так:

if (isset($this->request->post['fixed1stplus_cost'])) {
$data['fixed1stplus_cost'] = $this->request->post['fixed1stplus_cost'];
} else {
$data['fixed1stplus_cost'] = $this->config->get('fixed1stplus_cost');
}

if (isset($this->request->post['fixed1stplus_cost2'])) {
$data['fixed1stplus_cost2'] = $this->request->post['fixed1stplus_cost2'];
} else {
$data['fixed1stplus_cost2'] = $this->config->get('fixed1stplus_cost2');
}

Так мы создали новую переменную, для нашей добавленной стоимости. Ещё в этом файле нужно добавить описание поля:
$data['entry_cost'] = $this->language->get('entry_cost');
//наше новое поле
$data['entry_cost2'] = $this->language->get('entry_cost2');
entry_cost2 берётся из admin-language, значит, туда его тоже надо добавить.

Теперь нам нужно поле ввода в админке. Идём в admin-view, ищем блок:

<label class="col-sm-2 control-label" for="input-cost"><?php echo $entry_cost2; ?></label>
    <div class="col-sm-10">
    <input type="text" name="fixed1stplus_cost" value="<?php echo $fixed1stplus_cost; ?>" placeholder="<?php echo $entry_cost; ?>" id="input-cost" class="form-control" />
    </div>

Тоже копируем его, вставляем сразу под ним.

<label class="col-sm-2 control-label" for="input-cost"><?php echo $entry_cost; ?></label>
    <div class="col-sm-10">
    <input type="text" name="fixed1stplus_cost" value="<?php echo $fixed1stplus_cost; ?>" placeholder="<?php echo $entry_cost; ?>" id="input-cost" class="form-control" />
    </div>
<label class="col-sm-2 control-label" for="input-cost2"><?php echo $entry_cost2; ?></label>
    <div class="col-sm-10">
    <input type="text" name="fixed1stplus_cost2" value="<?php echo $fixed1stplus_cost2; ?>" placeholder="<?php echo $entry_cost2; ?>" id="input-cost2" class="form-control" />
    </div>

Всё, поле есть. Всё довольно логично и наглядно, не правда ли?

Осталось изменить расчёт стоимости. Здесь будет похитрее, но тоже несложно. Идём в catalog-model. Расчёт идёт в блоке if ($status) { ... } .
Добавим в начало этого блока:

//пишем во временную переменную фиксированную стоимость из нашего модуля
$cost = $this->config->get('fixed1stplus_cost');
//пишем фиксированную добавочную стоимость за грузо-место
$cost2 = $this->config->get('fixed1stplus_cost2');
$items = 0;

//считаем количество лотов в корзине
foreach ($this->cart->getProducts() as $product) {
if ($product['shipping']) {
$items += $product['quantity'];
}
}

//первый лот не считаем, за него фиксированная сумма
$items -= 1;

//добавляем к стоимости доставки фиксированную сумму за каждый лот
while ($items){

$items -= 1;
$cost += $cost2;
}

А затем в секции $quote_data['fixed1stplus'] = array( убираем оригинальный cost и вставляем наши:

'cost'         => $cost,
'cost2'        => $cost2,

Вот и всё. Сохраняем, загружаем на сервер, пользуемся на здоровье.

Скачать модуль для Opencart 2.3 "Стоимость доставки база + фиксированная сумма за лот или грузо-место".




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

Отправить комментарий