Sebagai pembangun, ia sentiasa menarik untuk membina kandungan tersuai dalam mana-mana rangka kerja, dan perkara yang sama berlaku untuk pemalam OpenCart.
Dalam siri dua bahagian ini, saya akan menerangkan pembangunan pemalam tersuai dalam OpenCart. Kami akan menyemak butiran pembangunan sambungan dalam OpenCart daripada perspektif pembangun pemula. Kami juga akan mencipta pemalam tersuai kecil untuk menunjukkan pelbagai aspek struktur pemalam OpenCart.
Di bahagian pertama, kami akan membina pemalam tersuai untuk memaparkan produk terbaharu di bahagian hadapan kedai dan anda akan dapat mengkonfigurasi kuantiti produk dari bahagian belakang itu sendiri. Itulah tujuan artikel ini - untuk membangunkan pemalam bahagian belakang dengan bentuk konfigurasi.
Saya menganggap anda telah menyediakan versi terkini OpenCart, yang pada masa penulisan ialah 2.1.0.2. Sebelum kita meneruskan untuk membangunkan pemalam sebenar, saya akan memperkenalkan anda kepada seni bina pemalam asas OpenCart dalam bahagian seterusnya.
OpenCart dibangunkan menggunakan salah satu corak pembangunan web (corak MVC) yang paling popular tetapi dengan sedikit perubahan, atau lebih tepat lagi saya akan katakan penambahan. Borang tambahan ialah komponen bahasa, menjadikannya MVCL dalam dunia OpenCart. Anda mungkin pernah mendengar tentang corak ini, tetapi sebagai permulaan, saya akan meringkaskan dengan cepat tentang semua itu.
M dalam MVC adalah singkatan kepada Model, iaitu tempat kebanyakan logik perniagaan berada. Dalam konteks OpenCart, ia adalah model yang berinteraksi dengan lapisan abstraksi pangkalan data untuk melakukan semua beban berat yang diperlukan untuk menjalankan kedai. Anda akan mendapati diri anda bekerja sebagai pembangun dalam bidang ini pada kebanyakan masa.
Seterusnya, V bermaksud View, yang mewakili lapisan pembentangan aplikasi. Seperti namanya, ia hanya mengendalikan logik pembentangan mana-mana halaman, dan kebanyakan masa ia menerima input daripada lapisan lain dan menghasilkan output XHTML. Logik perniagaan aplikasi harus menjauhi lapisan ini; ia hanya perlu mengambil berat tentang apa dan bukan bagaimana untuk melakukannya.
C (Pengawal) dalam MVC berada di hadapan segala-galanya dan bertanggungjawab untuk mengendalikan setiap permintaan dan mengendalikannya dengan sewajarnya. Kawasan ini mengandungi kebanyakan logik aplikasi, daripada memproses dan mengesahkan input pengguna kepada memuatkan model yang betul dan melihat komponen untuk menyediakan output halaman.
Akhirnya, terdapat add-on L, yang bermaksud bahasa. Ia menjadikan membina laman web berbilang bahasa mudah.
Ini ialah pandangan pantas seni bina OpenCart, ia akan lebih masuk akal apabila kami terus menerangkan setiap komponen secara mendalam.
Mari kita lihat senarai fail yang perlu dilaksanakan untuk pemalam bahagian belakang tersuai.
admin/language/english/module/recent_products.php
: Ini ialah fail yang menyimpan teg statik yang digunakan di seluruh kawasan aplikasi pentadbir. admin/language/english/module/recent_products.php
:这是一个保存在整个管理应用程序区域中使用的静态标签的文件。
admin/controller/module/recent_products.php
:它是一个控制器文件,保存我们模块的应用程序逻辑。admin/view/template/module/recent_products.tpl
:这是一个视图模板文件,包含 XHTML 代码。在下一节中,我们将创建上述每个文件,并进行深入说明。
按照惯例,我们需要将自定义插件文件放置在模块目录下。在这种情况下,当我们开发后端插件时,admin 下的目录将保存我们的文件。当然,根据上面所示的 OpenCart 架构,文件分布在不同的目录或组件中。
在本节中,我们将开始创建模块文件。首先,我们将创建一个语言文件 admin/language/english/module/recent_products.php
,其中包含以下内容。从 OpenCart 的角度来看,这是一个重要的文件,因为它是 OpenCart 检测到您的插件所必需的。
<?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!';
如您所见,我们将静态标签分配给 PHP 数组。稍后,当数组转换为 PHP 变量时,您将可以在视图模板文件中访问这些变量。
您可能还注意到,该文件是在 english 目录下创建的,因为它是商店的默认语言。当然,对于多语言网站,您需要确保也为其他语言创建它。例如,应在 admin/language/french/module/recent_products.php
创建同一文件的法语版本。
接下来,我们将创建最重要的插件文件之一——控制器文件。让我们继续创建包含以下内容的 admin/controller/module/recent_products.php
。
<?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; } }
它为我们的自定义插件定义了新类,该类扩展了基本 Controller
类。根据约定,类的名称应模仿文件所在的目录结构。因此,路径 controller/module/recent_products.php
会根据驼峰命名约定替换斜杠和下划线字符,转换为 ControllerModuleRecentProducts
admin/controller/module/recent_products.php
: Ia ialah fail pengawal yang memegang logik aplikasi modul kami.
admin/view/template/module/recent_products.tpl
: Ini ialah fail templat paparan yang mengandungi kod XHTML.
#🎜🎜#Dalam bahagian seterusnya, kami akan mencipta setiap fail di atas dan menerangkannya secara mendalam. #🎜🎜#
#🎜🎜# Mengikut konvensyen, kita perlu meletakkan fail pemalam tersuai dalam direktori Modul. Dalam kes ini, direktori di bawah pentadbir akan menyimpan fail kami semasa kami membangunkan pemalam bahagian belakang. Sudah tentu, mengikut seni bina OpenCart yang ditunjukkan di atas, fail diedarkan dalam direktori atau komponen yang berbeza. #🎜🎜#
#🎜🎜#Buat fail untuk pemalam bahagian belakang#🎜🎜#
#🎜🎜#Dalam bahagian ini, kami akan mula membuat fail modul. Mula-mula, kami akan mencipta fail bahasa admin/language/english/module/recent_products.php
dengan kandungan berikut. Dari perspektif OpenCart, ini adalah fail penting kerana ia diperlukan untuk OpenCart mengesan pemalam anda. #🎜🎜#
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')); }
admin/language/french/module/recent_products.php
. #🎜🎜#
#🎜🎜#Seterusnya, kami akan mencipta salah satu fail pemalam yang paling penting - fail pengawal. Mari teruskan dan buat admin/controller/module/recent_products.php
dengan kandungan berikut. #🎜🎜#
$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') ); }
Controller
. Mengikut konvensyen, nama kelas harus meniru struktur direktori di mana fail itu berada. Oleh itu, laluan controller/module/recent_products.php
ditukar kepada ControllerModuleRecentProducts
dengan menggantikan aksara slash dan underscore mengikut penamaan camelCase konvensyen! #🎜🎜#
接下来,有一个事实上的 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')); }
此外,我们还将 heading_title
和 text_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') ); }
如果模块之前已配置并处于编辑模式,则以下代码片段将填充默认模块配置。
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']); }
最后,我们加载常见的页面元素,例如页眉、页脚和左侧边栏。另外,它是加载实际视图文件 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">×</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; ?>
眼尖的用户已经注意到它只是显示从控制器文件传递的变量。除此之外,它是显示配置表单的简单 XHTML 代码,最重要的是它具有开箱即用的响应能力。
所以,这就是我们后端自定义插件的文件设置。
前往 OpenCart 后端并导航至扩展 > 模块。您应该在列表中看到最近的产品。单击+符号安装模块,如以下屏幕截图所示。
安装后,您将看到一个编辑图标。单击该按钮可打开模块配置表单。
在配置表单中,您可以设置要在前端块中显示的最近产品的数量。另外,不要忘记将状态字段设置为启用!保存模块,它应该看起来像这样。
模块中有一个新条目,标题为最近的产品 > 我最近的块插件。原因是您可以为不同的页面多次复制它!
所以,我们快完成了!我们在 OpenCart 中制作了一个成熟的后端自定义插件。在下一部分中,我们将介绍它的前端对应部分,它在前端显示一个漂亮的产品块!
今天,我们讨论了 OpenCart 中的自定义插件开发。在这个由两部分组成的系列的第一部分中,我们完成了后端插件开发并创建了一个提供配置表单的工作自定义插件。
如果您正在寻找可在自己的项目或自己的教育中使用的其他 OpenCart 工具、实用程序、扩展程序等,请查看我们在市场上提供的产品。
在下一部分中,我们将通过创建在前端显示产品列表的前端部分来完成该插件。如有任何疑问和反馈,请使用下面的评论源。
Atas ialah kandungan terperinci Bahagian Satu: Cara membuat pemalam tersuai dalam OpenCart 2.1.x.x. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!