Maison > interface Web > tutoriel HTML > Première partie : Comment créer un plugin personnalisé dans OpenCart 2.1.x.x

Première partie : Comment créer un plugin personnalisé dans OpenCart 2.1.x.x

WBOY
Libérer: 2023-09-08 23:05:13
original
755 Les gens l'ont consulté

En tant que développeur, c'est toujours passionnant de créer du contenu personnalisé dans n'importe quel framework, et il en va de même pour le plugin OpenCart.

Dans cette série en deux parties, j'expliquerai le développement de plugins personnalisés dans OpenCart. Nous passerons en revue les détails du développement d'extensions dans OpenCart du point de vue d'un développeur novice. Nous créerons également un petit plugin personnalisé pour démontrer divers aspects de la structure du plugin OpenCart.

Dans la première partie, nous créerons un plugin personnalisé pour afficher les derniers produits sur le frontend du magasin et vous pourrez configurer la quantité de produits à partir du backend lui-même. C'est le but de cet article : développer un plugin backend avec un formulaire de configuration.

Je suppose que vous avez configuré la dernière version d'OpenCart, qui au moment de la rédaction est la 2.1.0.2. Avant de passer au développement du plugin proprement dit, je vais vous présenter l'architecture de base du plugin OpenCart dans la section suivante.

Présentation de MVCL

OpenCart est développé en utilisant l'un des modèles de développement Web les plus populaires (modèle MVC) mais avec quelques légers changements, ou plutôt je dirais un ajout. Le formulaire ajouté est le composant de langage, ce qui en fait MVCL dans le monde OpenCart. Vous avez peut-être entendu parler de ce modèle, mais pour commencer, je vais résumer rapidement de quoi il s'agit.

Le M dans MVC signifie Modèle, où réside la majeure partie de la logique métier. Dans le contexte d'OpenCart, c'est le modèle qui interagit avec la couche d'abstraction de la base de données pour effectuer tout le gros du travail nécessaire au fonctionnement d'un magasin. Vous vous retrouverez la plupart du temps à travailler en tant que développeur dans ce domaine.

Ensuite, V signifie View, qui représente la couche de présentation de l'application. Comme son nom l'indique, il gère uniquement la logique de présentation de n'importe quelle page et, la plupart du temps, il reçoit des entrées d'autres couches et produit une sortie XHTML. La logique métier de l'application doit rester à l'écart de cette couche ; elle ne doit se soucier que de quoi et non de commentle faire.

Le C (contrôleur) dans MVC est devant tout et est responsable du traitement de chaque demande et de sa gestion en conséquence. Cette zone contient la majeure partie de la logique de l'application, depuis le traitement et la validation des entrées utilisateur jusqu'au chargement des composants de modèle et de vue corrects pour préparer la sortie de la page.

Enfin, il existe un module complémentaire L, qui signifie langue. Cela facilite la création de sites Web multilingues.

Ceci est un aperçu rapide de l'architecture OpenCart, cela aura plus de sens à mesure que nous continuerons à expliquer chaque composant en profondeur.

Le squelette de tout plugin OpenCart

Jetons un coup d'œil rapide à la liste des fichiers qui doivent être implémentés pour le plugin backend personnalisé.

  • admin/language/english/module/recent_products.php : Il s'agit d'un fichier qui contient les étiquettes statiques utilisées dans toute la zone d'application d'administration.
  • admin/controller/module/recent_products.php : C'est un fichier contrôleur qui contient la logique applicative de notre module.
  • admin/view/template/module/recent_products.tpl : Il s'agit d'un fichier de modèle de vue contenant du code XHTML.

Dans la section suivante, nous créerons chacun des fichiers ci-dessus et les expliquerons en profondeur.

Par convention, nous devons placer les fichiers de plug-ins personnalisés dans le répertoire module. Dans ce cas, le répertoire sous admin contiendra nos fichiers pendant que nous développons le plugin backend. Bien entendu, selon l'architecture OpenCart présentée ci-dessus, les fichiers sont répartis dans différents répertoires ou composants.

Créer des fichiers pour le plugin backend

Dans cette section, nous allons commencer à créer le fichier du module. Tout d'abord, nous allons créer un fichier de langue admin/language/english/module/recent_products.php avec le contenu suivant. Du point de vue d'OpenCart, il s'agit d'un fichier important car il est nécessaire à OpenCart pour détecter votre plugin.

<?php
// admin/language/english/module/recent_products.php
// Heading
$_['heading_title']    = 'Recent Products';

// Text
$_['text_module']      = 'Modules';
$_['text_success']     = 'Success: You have modified Recent Products module!';
$_['text_edit']        = 'Edit Recent Products Module';

// Entry
$_['entry_name']       = 'Module Name';
$_['entry_limit']      = 'Limit';
$_['entry_status']     = 'Status';

// Error
$_['error_permission'] = 'Warning: You do not have permission to modify Recent Products module!';
$_['error_name']       = 'Module Name must be between 3 and 64 characters!';
Copier après la connexion

Comme vous pouvez le voir, nous avons attribué la balise static au tableau PHP. Plus tard, lorsque les tableaux seront convertis en variables PHP, vous pourrez accéder à ces variables dans le fichier modèle de vue.

Vous remarquerez peut-être également que le fichier est créé dans le répertoire english car c'est la langue par défaut de la boutique. Bien entendu, avec un site Web multilingue, vous devez vous assurer de le créer également pour d’autres langues. Par exemple, une version française du même fichier devrait être créée sur admin/language/french/module/recent_products.php .

Ensuite, nous allons créer l'un des fichiers de plugin les plus importants : le fichier du contrôleur. Allons-y et créons admin/controller/module/recent_products.php avec le contenu suivant.

<?php
// admin/controller/module/recent_products.php
class ControllerModuleRecentProducts extends Controller {
    private $error = array();

    public function index() {
        $this->load->language('module/recent_products');

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

        $this->load->model('extension/module');

        if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
            if (!isset($this->request->get['module_id'])) {
                $this->model_extension_module->addModule('recent_products', $this->request->post);
            } else {
                $this->model_extension_module->editModule($this->request->get['module_id'], $this->request->post);
            }

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

            $this->response->redirect($this->url->link('extension/module', '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['entry_name'] = $this->language->get('entry_name');
        $data['entry_limit'] = $this->language->get('entry_limit');
        $data['entry_status'] = $this->language->get('entry_status');

        $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'] = '';
        }

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

        $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_module'),
            'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')
        );

        if (!isset($this->request->get['module_id'])) {
            $data['breadcrumbs'][] = array(
                'text' => $this->language->get('heading_title'),
                'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL')
            );
        } else {
            $data['breadcrumbs'][] = array(
                'text' => $this->language->get('heading_title'),
                'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL')
            );
        }

        if (!isset($this->request->get['module_id'])) {
            $data['action'] = $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL');
        } else {
            $data['action'] = $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL');
        }

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

        if (isset($this->request->get['module_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
            $module_info = $this->model_extension_module->getModule($this->request->get['module_id']);
        }

        if (isset($this->request->post['name'])) {
            $data['name'] = $this->request->post['name'];
        } elseif (!empty($module_info)) {
            $data['name'] = $module_info['name'];
        } else {
            $data['name'] = '';
        }

        if (isset($this->request->post['limit'])) {
            $data['limit'] = $this->request->post['limit'];
        } elseif (!empty($module_info)) {
            $data['limit'] = $module_info['limit'];
        } else {
            $data['limit'] = 5;
        }

        if (isset($this->request->post['status'])) {
            $data['status'] = $this->request->post['status'];
        } elseif (!empty($module_info)) {
            $data['status'] = $module_info['status'];
        } else {
            $data['status'] = '';
        }

        $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('module/recent_products.tpl', $data));
    }

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

        if ((utf8_strlen($this->request->post['name']) < 3) || (utf8_strlen($this->request->post['name']) > 64)) {
            $this->error['name'] = $this->language->get('error_name');
        }

        return !$this->error;
    }
}
Copier après la connexion

Il définit une nouvelle classe pour notre plugin personnalisé qui étend la base Controller 类。根据约定,类的名称应模仿文件所在的目录结构。因此,路径 controller/module/recent_products.php 会根据驼峰命名约定替换斜杠和下划线字符,转换为 ControllerModuleRecentProducts !

接下来,有一个事实上的 index 方法,当插件加载到前端时会调用该方法。所以,它是一个索引方法,定义了插件的大部分应用逻辑。

在当前应用程序的上下文中,简写 $this->load->language 加载相应的语言文件。在我们的例子中,它加载前面部分中定义的语言文件。语法非常简单,您只需传递前缀为 module/ 的插件名称即可。语言变量可以通过 $this->language->get 方法访问。

接下来,它使用文档对象的 setTitle 方法设置页面标题。

继续,简写 $this->load->model 用于加载模块模型。它是模型类,提供实用方法来保存模块参数等。

接下来,有一个重要的代码片段,如下所示,用于检查是否是 POST 数据提交,并在这种情况下保存模块配置。

if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
    if (!isset($this->request->get['module_id'])) {
        $this->model_extension_module->addModule('recent_products', $this->request->post);
    } else {
        $this->model_extension_module->editModule($this->request->get['module_id'], $this->request->post);
    }

    $this->session->data['success'] = $this->language->get('text_success');
    $this->response->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));
}
Copier après la connexion

此外,我们还将 heading_titletext_edit 等语言标签分配给 $data 数组,以便我们可以使用它们在视图模板文件中。

接下来,有一个片段可以为配置页面构建正确的面包屑链接。

$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_module'),
    'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')
);

if (!isset($this->request->get['module_id'])) {
    $data['breadcrumbs'][] = array(
        'text' => $this->language->get('heading_title'),
        'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL')
    );
} else {
    $data['breadcrumbs'][] = array(
        'text' => $this->language->get('heading_title'),
        'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL')
    );
}
Copier après la connexion

如果模块之前已配置并处于编辑模式,则以下代码片段将填充默认模块配置。

if (isset($this->request->get['module_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
    $module_info = $this->model_extension_module->getModule($this->request->get['module_id']);
}
Copier après la connexion

最后,我们加载常见的页面元素,例如页眉、页脚和左侧边栏。另外,它是加载实际视图文件 recent_products.tpl 并显示配置表单的 $this->load->view 简写。

控制器文件中有一些重要的注释需要记住。您会看到很多类似 $this->load->ELEMENT 的调用,其中 ELEMENT 可以是视图、模型或语言。它加载相应的视图、模型和语言组件。

今天文章的下一个也是最后一个文件是视图模板文件admin/view/template/module/recent_products.tpl。继续创建它!

<!-- admin/view/template/module/recent_products.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-recent-products" 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-recent-products" class="form-horizontal">
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-name"><?php echo $entry_name; ?></label>
            <div class="col-sm-10">
              <input type="text" name="name" value="<?php echo $name; ?>" placeholder="<?php echo $entry_name; ?>" id="input-name" class="form-control" />
              <?php if ($error_name) { ?>
              <div class="text-danger"><?php echo $error_name; ?></div>
              <?php } ?>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-limit"><?php echo $entry_limit; ?></label>
            <div class="col-sm-10">
              <input type="text" name="limit" value="<?php echo $limit; ?>" placeholder="<?php echo $entry_limit; ?>" id="input-limit" 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="status" id="input-status" class="form-control">
                <?php if ($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>
        </form>
      </div>
    </div>
  </div>
</div>
<?php echo $footer; ?>
Copier après la connexion

眼尖的用户已经注意到它只是显示从控制器文件传递的变量。除此之外,它是显示配置表单的简单 XHTML 代码,最重要的是它具有开箱即用的响应能力。

所以,这就是我们后端自定义插件的文件设置。

启用插件

前往 OpenCart 后端并导航至扩展 > 模块。您应该在列表中看到最近的产品。单击+符号安装模块,如以下屏幕截图所示。

第一部分:如何在 OpenCart 2.1.x.x 中创建自定义插件

安装后,您将看到一个编辑图标。单击该按钮可打开模块配置表单。

第一部分:如何在 OpenCart 2.1.x.x 中创建自定义插件

在配置表单中,您可以设置要在前端块中显示的最近产品的数量。另外,不要忘记将状态字段设置为启用!保存模块,它应该看起来像这样。

第一部分:如何在 OpenCart 2.1.x.x 中创建自定义插件

模块中有一个新条目,标题为最近的产品 > 我最近的块插件。原因是您可以为不同的页面多次复制它!

所以,我们快完成了!我们在 OpenCart 中制作了一个成熟的后端自定义插件。在下一部分中,我们将介绍它的前端对应部分,它在前端显示一个漂亮的产品块!

结论

今天,我们讨论了 OpenCart 中的自定义插件开发。在这个由两部分组成的系列的第一部分中,我们完成了后端插件开发并创建了一个提供配置表单的工作自定义插件。

如果您正在寻找可在自己的项目或自己的教育中使用的其他 OpenCart 工具、实用程序、扩展程序等,请查看我们在市场上提供的产品。

在下一部分中,我们将通过创建在前端显示产品列表的前端部分来完成该插件。如有任何疑问和反馈,请使用下面的评论源。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal