Статьи

Создайте пользовательский плагин в OpenCart 2.1.xx: часть вторая

Если вы еще не прошли первую часть этой серии, я бы порекомендовал вам сделать это, поскольку перед тем, как приступить к разработке файлов в этой статье, это необходимо сделать.

Как быстрое напоминание, мы разрабатываем плагин Recent Products, который перечисляет X продуктов во внешнем интерфейсе. Вы можете настроить количество отображаемых продуктов из формы внутренней конфигурации, созданной в первой части этой серии. Мы также рассмотрели архитектуру плагинов OpenCart, и она также будет применена к разработке внешних плагинов.

Как упоминалось ранее, в ходе этого урока мы будем разрабатывать файлы внешних модулей, поэтому давайте кратко рассмотрим список файлов, которые необходимо реализовать.

  • catalog/language/english/module/recent_products.php : это файл, который содержит статические метки, используемые во всей области приложения.
  • catalog/controller/module/recent_products.php : это файл контроллера, который содержит логику приложения нашего модуля.
  • catalog/model/module/recent_products.php : это файл модели, который используется для взаимодействия с базой данных для получения продуктов.
  • catalog/view/theme/default/template/module/recent_products.tpl : это файл шаблона представления и содержит код XHTML.

Очевидное отличие, которое вы заметили здесь, заключается в том, что это каталог каталога, который содержит файлы внешних модулей, а не каталог администратора, который использовался для создания файлов внутренних модулей. Кроме того, есть файл модели, который не был создан для серверной части, который содержит бизнес-логику нашего плагина для извлечения последних продуктов из базы данных.

Другая важная вещь, на которую следует обратить внимание — это размещение файла шаблона представления recent_products.tpl . Как правило, во внешнем интерфейсе у вас будет более одной темы, и это обрабатывается дополнительным каталогом тем. Это стандартная директория тем OpenCart, которая содержит большинство файлов шаблонов.

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

Для начала давайте создадим catalog/language/english/module/recent_products.php языковых файлов catalog/language/english/module/recent_products.php со следующим содержимым.

1
2
3
4
<?php
// catalog/language/english/module/recent_products.php
// Heading
$_[‘heading_title’] = ‘Recent Products’;

Он используется для настройки статических меток, которые будут использоваться в файле шаблона представления. Он практически идентичен языку администратора.

Далее мы создадим файл контроллера, который должен быть помещен в catalog/controller/module/recent_products.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
// catalog/controller/module/recent_products.php
class ControllerModuleRecentProducts extends Controller {
    public function index($setting) {
        $this->load->language(‘module/recent_products’);
 
        $data[‘heading_title’] = $this->language->get(‘heading_title’);
 
        $this->load->model(‘module/recent_products’);
 
        $this->load->model(‘tool/image’);
 
        $data[‘products’] = array();
 
        $results = $this->model_module_recent_products->getRecentProducts($setting[‘limit’]);
 
        if ($results) {
            foreach ($results as $result) {
                if ($result[‘image’]) {
                    $image = $this->model_tool_image->resize($result[‘image’], 100, 100);
                } else {
                    $image = $this->model_tool_image->resize(‘placeholder.png’, 100, 100);
                }
 
                if (($this->config->get(‘config_customer_price’) && $this->customer->isLogged()) || !$this->config->get(‘config_customer_price’)) {
                    $price = $this->currency->format($this->tax->calculate($result[‘price’], $result[‘tax_class_id’], $this->config->get(‘config_tax’)));
                } else {
                    $price = false;
                }
 
                if ((float)$result[‘special’]) {
                    $special = $this->currency->format($this->tax->calculate($result[‘special’], $result[‘tax_class_id’], $this->config->get(‘config_tax’)));
                } else {
                    $special = false;
                }
 
                $data[‘products’][] = array(
                    ‘product_id’ => $result[‘product_id’],
                    ‘thumb’ => $image,
                    ‘name’ => $result[‘name’],
                    ‘description’ => utf8_substr(strip_tags(html_entity_decode($result[‘description’], ENT_QUOTES, ‘UTF-8’)), 0, $this->config->get(‘config_product_description_length’)) .
                    ‘price’ => $price,
                    ‘special’ => $special,
                    ‘href’ => $this->url->link(‘product/product’, ‘product_id=’ . $result[‘product_id’])
                );
            }
 
            if (file_exists(DIR_TEMPLATE . $this->config->get(‘config_template’) . ‘/template/module/recent_products.tpl’)) {
                return $this->load->view($this->config->get(‘config_template’) . ‘/template/module/recent_products.tpl’, $data);
            } else {
                return $this->load->view(‘default/template/module/recent_products.tpl’, $data);
            }
        }
    }
}

Опять же, index метод — это место, куда должна входить большая часть нашего кода. Как и в большинстве других плагинов, вы обнаружите, что в методе индекса доступен параметр $setting . Вспомните форму конфигурации администратора, разработанную в первой части, которая использовалась для настройки параметров плагина — вот что обозначает переменная $setting . Он содержит значения конфигурации плагина в виде массива.

Сокращение $this->load->language загружает языковой файл внешнего плагина, и мы уже подробно обсуждали его в первой части. Аналогичным образом, сокращение $this->load->model загружает файл модели плагина, созданный в catalog/model/module/recent_products.php . Мы также загружаем модель Image определенную в каталоге tool поскольку она содержит служебные методы для изменения размера изображений.

Самый важный вызов в методе index — это вызов метода getRecentProducts который предоставляет массив последних продуктов из базы данных. Конечно, мы увидим это подробно во время обсуждения файла модели. В качестве аргумента метода передается значение $setting['limit'] настроенное в форме внутренней конфигурации.

1
$results = $this->model_module_recent_products->getRecentProducts($setting[‘limit’]);

Далее мы перебираем массив продуктов и подготавливаем массив $data['products'] который будет использоваться в файле шаблона представления. В этом процессе мы используем метод resize класса модели Image для создания миниатюрных изображений, так как не имеет смысла отображать оригинальные изображения продукта во внешнем интерфейсе.

Вы также найдете $this->config->get вроде фрагментов, которые используются для извлечения глобальных значений конфигурации хранилища. Вы можете настроить параметры своего магазина в разделе « Система»> «Настройки» .

Кроме того, сокращенная $this->url->link используется для создания SEO- $this->url->link на страницы товаров. Наконец, есть фрагмент для загрузки файла шаблона recent_products.tpl который готовит фактический вывод с использованием массива $data .

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

1
2
3
4
5
if (file_exists(DIR_TEMPLATE . $this->config->get(‘config_template’) . ‘/template/module/recent_products.tpl’)) {
    return $this->load->view($this->config->get(‘config_template’) . ‘/template/module/recent_products.tpl’, $data);
} else {
    return $this->load->view(‘default/template/module/recent_products.tpl’, $data);
}

Итак, это конец файла контроллера. Давайте продолжим и создадим файл модели в catalog/model/module/recent_products.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<?php
// catalog/model/module/recent_products.php
class ModelModuleRecentProducts extends Model {
    public function getRecentProducts($limit) {
        $this->load->model(‘catalog/product’);
        $product_data = $this->cache->get(‘product.recent.’ . (int)$this->config->get(‘config_language_id’) . ‘.’ . (int)$this->config->get(‘config_store_id’) . ‘.’ . $this->config->get(‘config_customer_group_id’) . ‘.’ . (int)$limit);
 
        if (!$product_data) {
            $query = $this->db->query(«SELECT p.product_id FROM » . DB_PREFIX . «product p LEFT JOIN » . DB_PREFIX . «product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = ‘1’ AND p.date_available <= NOW() AND p2s.store_id = ‘» . (int)$this->config->get(‘config_store_id’) . «‘ ORDER BY p.date_added DESC LIMIT » . (int)$limit);
 
            foreach ($query->rows as $result) {
                $product_data[$result[‘product_id’]] = $this->model_catalog_product->getProduct($result[‘product_id’]);
            }
 
            $this->cache->set(‘product.recent.’ . (int)$this->config->get(‘config_language_id’) . ‘.’ . (int)$this->config->get(‘config_store_id’) . ‘.’ . $this->config->get(‘config_customer_group_id’) . ‘.’ . (int)$limit, $product_data);
        }
 
        return $product_data;
    }
}

Согласно соглашениям, имя класса модели начинается с ключевого слова Model и следует структуре каталогов. Он также расширяет базовый класс Model который предоставляет служебные объекты и методы для взаимодействия с базой данных.

Мы также загружаем модель Product определенную в catalog каталога, используя синтаксис $this->load->model('catalog/product') , поскольку нам нужно будет использовать методы, определенные в этом классе.

Несколько других удобных сокращений: $this->cache->set и $this->cache->get . Первый используется для установки значения в кеше, а второй получает уже сохраненное значение кеша по ключу. Хорошей привычкой является правильное использование кэширования для улучшения общей производительности вашего магазина.

Наконец, мы выполняем запрос к базе данных, чтобы получить последние продукты, и синтаксис $this->db->query помогает нам в этом. Это сокращение, которое запускает метод запроса класса базы данных.

Далее мы перебираем все записи о продукте и загружаем информацию о продукте, вызывая метод getProduct класса модели Product . В конце мы сохраняем информацию о массиве в кеш, чтобы в последующих запросах нам не приходилось снова выполнять всю тяжелую работу!

Наконец, есть только файл представления recent_products.tpl который необходимо создать, чтобы завершить наш пользовательский плагин. Давайте сделаем это, создав его в catalog/view/theme/default/template/module/recent_products.tpl .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!— catalog/view/theme/default/template/module/recent_products.tpl —>
<h3><?php echo $heading_title;
<div class=»row»>
  <?php foreach ($products as $product) { ?>
  <div class=»product-layout col-lg-3 col-md-3 col-sm-6 col-xs-12″>
    <div class=»product-thumb transition»>
      <div class=»image»><a href=»<?php echo $product[‘href’]; ?>»><img src=»<?php echo $product[‘thumb’]; ?>» alt=»<?php echo $product[‘name’]; ?>» title=»<?php echo $product[‘name’]; ?>» class=»img-responsive» /></a></div>
      <div class=»caption»>
        <h4><a href=»<?php echo $product[‘href’]; ?>»><?php echo $product[‘name’];
        <p><?php echo $product[‘description’];
        <?php if ($product[‘price’]) { ?>
        <p class=»price»>
          <?php if (!$product[‘special’]) { ?>
          <?php echo $product[‘price’];
          <?php } else { ?>
          <span class=»price-new»><?php echo $product[‘special’];
          <?php } ?>
        </p>
        <?php } ?>
      </div>
    </div>
  </div>
  <?php } ?>
</div>

В файле представления мы просто перебираем массив $products предоставляемый контроллером, для создания списка товаров XHTML.

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

Чтобы любой плагин отображался во внешнем интерфейсе, нам нужно назначить его одному из доступных макетов. В качестве примера, мы продолжим и назначим наш плагин на позицию Content Top .

Перейдите на сервер и перейдите в Система> Дизайн> Макеты . Это должно перечислить все доступные макеты в вашем магазине. Отредактируйте макет Home , и он откроет вам экран редактирования макета. Вам просто нужно добавить новую запись модуля, как показано на следующем скриншоте.

Назначить макет

Как видите, мы подняли плагин « Недавние продукты»> «Мои недавние блоки» и присвоили его верхней позиции контента . Сохраните настройки, и все готово!

Перейдите к внешнему интерфейсу, и вы сможете увидеть довольно приличный блок « Последние продукты» , как показано на следующем снимке экрана.

Предварительный просмотр

Итак, на этом наша серия разработки плагинов в OpenCart заканчивается. Хотя серия была предназначена для начинающих, она также должна содержать хороший шаблон плагина, который можно расширить в соответствии с вашими требованиями.

Я рекомендую вам изучить его самостоятельно и добавить больше функциональных возможностей. Это должно быть достойное упражнение после выхода из этого урока!

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

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

Не стесняйтесь оставлять свои отзывы и запросы, используя ленту комментариев ниже!