Создание кастомного расширения order total в OpenCart

18 Мар 2023г. в 15:35

Чтобы создать кастомное расширение order totals, нам необходимо создать файлы back end и front end. Файлы back end отвечают за форму настроек, а файлы front end определяют логику расширения. Естественно, OpenCart не определит ваше расширение на странице корзины без файлов front end.

Будем работать в последней версии OpenCart. Также предполагаю, что вы знаете основы процесс модульной разработки в OpenCart. Перейдем сразу к делу!

Файлы back end
В этом разделе мы создадим файлы back end. В конце раздела в списке расширений order totals появится наше кастомное. Также вы сможете установить и настроить его через кастомную форму настроек.

Создайте файл контроллера admin/controller/total/customot.php со следующим кодом.

<?php
class ControllerTotalCustomot extends Controller {
private $error = array();

public function index() {
$this->load->language('total/customot');

$this->document->setTitle($this->language->get('heading_title'));

$this->load->model('setting/setting');

if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$this->model_setting_setting->editSetting('customot', $this->request->post);

$this->session->data['success'] = $this->language->get('text_success');

$this->response->redirect($this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL'));
}

$data['heading_title'] = $this->language->get('heading_title');

$data['text_edit'] = $this->language->get('text_edit');
$data['text_enabled'] = $this->language->get('text_enabled');
$data['text_disabled'] = $this->language->get('text_disabled');
$data['text_none'] = $this->language->get('text_none');

$data['entry_customtax'] = $this->language->get('entry_customtax');
$data['entry_status'] = $this->language->get('entry_status');
$data['entry_sort_order'] = $this->language->get('entry_sort_order');

$data['button_save'] = $this->language->get('button_save');
$data['button_cancel'] = $this->language->get('button_cancel');

if (isset($this->error['warning'])) {
$data['error_warning'] = $this->error['warning'];
} else {
$data['error_warning'] = '';
}

$data['breadcrumbs'] = array();

$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
);

$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_total'),
'href' => $this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL')
);

$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('total/customot', 'token=' . $this->session->data['token'], 'SSL')
);

$data['action'] = $this->url->link('total/customot', 'token=' . $this->session->data['token'], 'SSL');

$data['cancel'] = $this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL');

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

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

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

$data['header'] = $this->load->controller('common/header');
$data['column_left'] = $this->load->controller('common/column_left');
$data['footer'] = $this->load->controller('common/footer');

$this->response->setOutput($this->load->view('total/customot.tpl', $data));
}

protected function validate() {
if (!$this->user->hasPermission('modify', 'total/customot')) {
$this->error['warning'] = $this->language->get('error_permission');
}

return !$this->error;
}
}

<?php
class ControllerTotalCustomot extends Controller {
private $error = array();

public function index() {
$this->load->language('total/customot');

$this->document->setTitle($this->language->get('heading_title'));

$this->load->model('setting/setting');

if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$this->model_setting_setting->editSetting('customot', $this->request->post);

$this->session->data['success'] = $this->language->get('text_success');

$this->response->redirect($this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL'));
}

$data['heading_title'] = $this->language->get('heading_title');

$data['text_edit'] = $this->language->get('text_edit');
$data['text_enabled'] = $this->language->get('text_enabled');
$data['text_disabled'] = $this->language->get('text_disabled');
$data['text_none'] = $this->language->get('text_none');

$data['entry_customtax'] = $this->language->get('entry_customtax');
$data['entry_status'] = $this->language->get('entry_status');
$data['entry_sort_order'] = $this->language->get('entry_sort_order');

$data['button_save'] = $this->language->get('button_save');
$data['button_cancel'] = $this->language->get('button_cancel');

if (isset($this->error['warning'])) {
$data['error_warning'] = $this->error['warning'];
} else {
$data['error_warning'] = '';
}

$data['breadcrumbs'] = array();

$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
);

$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_total'),
'href' => $this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL')
);

$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('total/customot', 'token=' . $this->session->data['token'], 'SSL')
);

$data['action'] = $this->url->link('total/customot', 'token=' . $this->session->data['token'], 'SSL');

$data['cancel'] = $this->url->link('extension/total', 'token=' . $this->session->data['token'], 'SSL');

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

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

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

$data['header'] = $this->load->controller('common/header');
$data['column_left'] = $this->load->controller('common/column_left');
$data['footer'] = $this->load->controller('common/footer');

$this->response->setOutput($this->load->view('total/customot.tpl', $data));
}

protected function validate() {
if (!$this->user->hasPermission('modify', 'total/customot')) {
$this->error['warning'] = $this->language->get('error_permission');
}

return !$this->error;
}
}
Как видите, это довольно стандартный контроллер back end в OpenCart. Основная задача файла контроллера – установка лейблов и других элементов, которые будут вызываться на форме настроек. Также он обрабатывает отправку формы путем валидации и сохранения значений формы в базе данных.

Теперь создайте языковой файл admin/language/english/total/customot.php со следующим кодом.

<?php
// Heading
$_['heading_title'] = 'Custom Order Total';

// Text
$_['text_success'] = 'Success: You have modified custom order total!';
$_['text_edit'] = 'Edit Custom Order Total';

// Entry
$_['entry_customtax'] = 'Custom Tax (%)';
$_['entry_status'] = 'Status';
$_['entry_sort_order'] = 'Sort Order';

// Error
$_['error_permission'] = 'Warning: You do not have permission to modify custom order total!';

<?php
// Heading
$_['heading_title'] = 'Custom Order Total';

// Text
$_['text_success'] = 'Success: You have modified custom order total!';
$_['text_edit'] = 'Edit Custom Order Total';

// Entry
$_['entry_customtax'] = 'Custom Tax (%)';
$_['entry_status'] = 'Status';
$_['entry_sort_order'] = 'Sort Order';

// Error
$_['error_permission'] = 'Warning: You do not have permission to modify custom order total!';
Код понять не трудно, здесь просто задаются лейблы.

И наконец, создайте файл шаблона представления admin/view/template/total/customot.tpl.

<?php echo $header; ?><?php echo $column_left; ?>
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="pull-right">
<button type="submit" form="form-customot" data-toggle="tooltip" title="<?php echo $button_save; ?>" class="btn btn-primary"><i class="fa fa-save"></i></button>
<a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a>
</div>
<h1><?php echo $heading_title; ?></h1>
<ul class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li>
<?php } ?>
</ul>
</div>
</div>
<div class="container-fluid">
<?php if ($error_warning) { ?>
<div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> <?php echo $error_warning; ?>
<button type="button" class="close" data-dismiss="alert">&times;</button>
</div>
<?php } ?>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-pencil"></i> <?php echo $text_edit; ?></h3>
</div>
<div class="panel-body">
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-customot" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label" for="input-customtax"><?php echo $entry_customtax; ?></label>
<div class="col-sm-10">
<input type="text" name="customot_customtax" value="<?php echo $customot_customtax; ?>" placeholder="<?php echo $entry_customtax; ?>" id="input-customtax" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="input-status"><?php echo $entry_status; ?></label>
<div class="col-sm-10">
<select name="customot_status" id="input-status" class="form-control">
<?php if ($customot_status) { ?>
<option value="1" selected="selected"><?php echo $text_enabled; ?></option>
<option value="0"><?php echo $text_disabled; ?></option>
<?php } else { ?>
<option value="1"><?php echo $text_enabled; ?></option>
<option value="0" selected="selected"><?php echo $text_disabled; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="input-sort-order"><?php echo $entry_sort_order; ?></label>
<div class="col-sm-10">
<input type="text" name="customot_sort_order" value="<?php echo $customot_sort_order; ?>" placeholder="<?php echo $entry_sort_order; ?>" id="input-sort-order" class="form-control" />
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<?php echo $footer; ?>

<?php echo $header; ?><?php echo $column_left; ?>
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="pull-right">
<button type="submit" form="form-customot" data-toggle="tooltip" title="<?php echo $button_save; ?>" class="btn btn-primary"><i class="fa fa-save"></i></button>
<a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a>
</div>
<h1><?php echo $heading_title; ?></h1>
<ul class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li>
<?php } ?>
</ul>
</div>
</div>
<div class="container-fluid">
<?php if ($error_warning) { ?>
<div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> <?php echo $error_warning; ?>
<button type="button" class="close" data-dismiss="alert">&times;</button>
</div>
<?php } ?>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-pencil"></i> <?php echo $text_edit; ?></h3>
</div>
<div class="panel-body">
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-customot" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label" for="input-customtax"><?php echo $entry_customtax; ?></label>
<div class="col-sm-10">
<input type="text" name="customot_customtax" value="<?php echo $customot_customtax; ?>" placeholder="<?php echo $entry_customtax; ?>" id="input-customtax" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="input-status"><?php echo $entry_status; ?></label>
<div class="col-sm-10">
<select name="customot_status" id="input-status" class="form-control">
<?php if ($customot_status) { ?>
<option value="1" selected="selected"><?php echo $text_enabled; ?></option>
<option value="0"><?php echo $text_disabled; ?></option>
<?php } else { ?>
<option value="1"><?php echo $text_enabled; ?></option>
<option value="0" selected="selected"><?php echo $text_disabled; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="input-sort-order"><?php echo $entry_sort_order; ?></label>
<div class="col-sm-10">
<input type="text" name="customot_sort_order" value="<?php echo $customot_sort_order; ?>" placeholder="<?php echo $entry_sort_order; ?>" id="input-sort-order" class="form-control" />
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<?php echo $footer; ?>
В файле хранится XHTML код нашей формы настроек.

С back end закончили. Перейдите в Extensions > Order Totals. Расширение Custom Order Total должно быть в списке вместе с другими расширениями. Давайте установим и настроим его, как показано на скриншоте ниже.

Я задал Custom Tax значение 5, то есть поверх общей суммы заказа будем взиматься еще 5%. Заполните значения и сохраните форму.

Файлы front end
В этом разделе мы создадим файлы front end, чтобы наше расширение определялось на странице оформления заказа.

Создайте файл модели catalog/model/total/customot.php со следующим кодом.

<?php
class ModelTotalCustomot extends Model {
public function getTotal(&$total_data, &$total, &$taxes) {
$this->load->language('total/customot');

// get customtax
$customtax_percentage = $this->config->get('customot_customtax');

if ($customtax_percentage > 0) {
$customtax_value = round(($total * $customtax_percentage) / 100);


$total_data[] = array(
'code' => 'customot',
'title' => $this->language->get('text_customot'),
'value' => $customtax_value,
'sort_order' => $this->config->get('customot_sort_order')
);

$total += $customtax_value;
}
}
}

<?php
class ModelTotalCustomot extends Model {
public function getTotal(&$total_data, &$total, &$taxes) {
$this->load->language('total/customot');

// get customtax
$customtax_percentage = $this->config->get('customot_customtax');

if ($customtax_percentage > 0) {
$customtax_value = round(($total * $customtax_percentage) / 100);


$total_data[] = array(
'code' => 'customot',
'title' => $this->language->get('text_customot'),
'value' => $customtax_value,
'sort_order' => $this->config->get('customot_sort_order')
);

$total += $customtax_value;
}
}
}
Важный файл и центральная логика нашего расширения. OpenCart вызывает метод getTotal для всех расширений order totals на странице оформления заказа. Обратите внимание на важные аргументы $total_data, $total и $taxes.

Переменная $total_data представляет собой массив всех данных расширений order total. Переменная $total – общая сумма заказа, а $taxes хранит применяемый налог.

В этом методе мы получаем значение Custom Tax, которое была задано в форме настроек на стороне back end. Далее мы вычисляем суму кастомного налога и присваиваем ее переменной $customtax_value. Затем мы записываем нашу информацию о расширении в массив $total_data и добавляем кастомный налог в переменную $total.

Нам осталось создать языковой файл catalog/language/english/total/customot.php со следующим кодом.

<?php
$_['text_customot'] = 'Custom Tax Value';

<?php
$_['text_customot'] = 'Custom Tax Value';
С front end закончили!

Демо на front end
Добавьте товары в корзину, и вы увидите, как наш кастомный налог применился к общей сумме, как показано на скриншоте ниже.

Таким образом, вы можете влиять на общую сумму заказа через расширение order totals.

Заключение

В этой статье мы узнали, как создать кастомное расширение order totals, а также как манипулировать общей суммой заказа. Очень удобно прикреплять любой кастомный налог или скидку. Предложения и вопросы приветствуются!