zoukankan      html  css  js  c++  java
  • opencart 模块开发详解

    opencart 模块开发详解

    帖子xiekanxiyang » 2013年 7月 11日 10:17 pm

    opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每个实例可以指定它出现在哪个页面 这样更好的实现了代码的可重用性,可以达到更好的页面布局的可调节性. Opencar内置了几个模块,但实际应用中我们经常要根据需要开发自己模块,现在我给大家介绍下opencart的模块开发的细节


    开发步骤:
    首先:模块代码也分前台,后台. 后台功能是模块的安装,编辑,模块实例参数的设置等,而前台代码相对简单些就是将内容调出来显示在指定位置.
    OC 是MVC+L设计 所以我们加一个功能时候通常会有四个文件 也就是:控制器(C)、模型(M)、视图(V)和 语言文件(L) 今天我们讲的模块有点特殊它的数据是存放在setting表里的,这样所有的模块model用setting的model就可以了 不需要另外写了, 这样我们开发新的模块,有这3个文件就可以了 前后台都一样,文件分别是 C+V+L; 它们分别放在各自文件下的module文件夹里,如果开发的话找个oc内置模块的将这3个文件复制份简单的替换下,如果新加的字段加上就可以了 , 就能制作个新的模块。前台同样也有3个文件复制小改下就ok!这样一个新的模块就完成了。

    模块安装:
    在OC后台 Extensions > Moules 是模块管理页, 打开这个页它会检索admincontrollermodule的所有文件,提取文件名作为模块名称 所以在这文件夹中的所有文件他都会认为是一个模块. 然后在数据库的oc_extension表中查询type为module中的记录,其中code字段就是已安装的模块名称。 也就是说在文件夹里的文件是所有的模块, 如果同时存在于oc_extension中,就认为是已安装的模块。 如果没有安装点击 安装后模块名插入此表。

    模块后台代码分析:
    以account模块为例,控制器代码如下 我加了注释供大家参考

        <?php
        class ControllerModuleAccount extends Controller {
           private $error = array();
           
           public function index() {   
              $this->language->load('module/account');             //导入语言文件
    
              $this->document->setTitle($this->language->get('heading_title'));     //将语言文件里的 heading_title 设为标题
              
              $this->load->model('setting/setting');              //加载 setting model 因为模型的实例的参数是放到oc_setting表中的
                    
              if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {   //如果有POST数据  并且检测用户权限通过
                 $this->model_setting_setting->editSetting('account', $this->request->post);     //将数据更新到oc_setting表   
                       
                 $this->session->data['success'] = $this->language->get('text_success');
                          
                 $this->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));//更新完成跳回模型管理页
              }
    
              
              //以下内容为语言文件的内容赋值到相应变量 
              $this->data['heading_title'] = $this->language->get('heading_title');
    
              $this->data['text_enabled'] = $this->language->get('text_enabled');
              $this->data['text_disabled'] = $this->language->get('text_disabled');
              $this->data['text_content_top'] = $this->language->get('text_content_top');
              $this->data['text_content_bottom'] = $this->language->get('text_content_bottom');      
              $this->data['text_column_left'] = $this->language->get('text_column_left');
              $this->data['text_column_right'] = $this->language->get('text_column_right');
              
              $this->data['entry_layout'] = $this->language->get('entry_layout');
              $this->data['entry_position'] = $this->language->get('entry_position');
              $this->data['entry_status'] = $this->language->get('entry_status');
              $this->data['entry_sort_order'] = $this->language->get('entry_sort_order');
              
              $this->data['button_save'] = $this->language->get('button_save');
              $this->data['button_cancel'] = $this->language->get('button_cancel');
              $this->data['button_add_module'] = $this->language->get('button_add_module');
              $this->data['button_remove'] = $this->language->get('button_remove');
              
               if (isset($this->error['warning'])) {
                 $this->data['error_warning'] = $this->error['warning'];
              } else {
                 $this->data['error_warning'] = '';
              }
    
                $this->data['breadcrumbs'] = array();
    
                //面包屑导航
                 $this->data['breadcrumbs'][] = array(
                     'text'      => $this->language->get('text_home'),
                 'href'      => $this->url->link('common/home', 'token=' . $this->session->data['token'], 'SSL'),
                    'separator' => false
                 );
    
                 $this->data['breadcrumbs'][] = array(
                     'text'      => $this->language->get('text_module'),
                 'href'      => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'),
                    'separator' => ' :: '
                 );
              
                 $this->data['breadcrumbs'][] = array(
                     'text'      => $this->language->get('heading_title'),
                 'href'      => $this->url->link('module/account', 'token=' . $this->session->data['token'], 'SSL'),
                    'separator' => ' :: '
                 );
              
                 //post提交链接
              $this->data['action'] = $this->url->link('module/account', 'token=' . $this->session->data['token'], 'SSL');
              //取消按键的链接
              $this->data['cancel'] = $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL');
    
              $this->data['modules'] = array();
              
              //获取模型的参数
              if (isset($this->request->post['account_module'])) {
                 $this->data['modules'] = $this->request->post['account_module'];
              } elseif ($this->config->get('account_module')) {
                 $this->data['modules'] = $this->config->get('account_module');
              }   
              
              $this->load->model('design/layout');
              
              //获取布局
              $this->data['layouts'] = $this->model_design_layout->getLayouts();
    
              //导入模板文件
              $this->template = 'module/account.tpl';
              $this->children = array(
                 'common/header',
                 'common/footer'
              );
                    
              $this->response->setOutput($this->render());
           }
           
           //检测用户权限
           protected function validate() {
              if (!$this->user->hasPermission('modify', 'module/account')) {
                 $this->error['warning'] = $this->language->get('error_permission');
              }
              
              if (!$this->error) {
                 return true;
              } else {
                 return false;
              }   
           }
        }
        ?>

    图片是模块参数在setting表中的记录 其中value就是参数数组序列化后的字符串

    语言文件和模板就很简单了 这里就不说了

    前台代码也很简单只是查出数据显示出来 一看就明白 也就不说了

    模块前台显示机制:
    模块设置时候会有个位置(position)选项 也就是模块在你指定页中的位置 有四个选项:content Top 、content Bottom 、column Left 、column Right四个选项。这里你选择哪个选项就会在哪个位置调用。
    这 四个选项对应会有四个文件(控制器) 在前台控制器中catalogcontrollercommon这个路径下的同名文件便是,这里就是调用的地方。拿content Top为例所有位置为content Top的模块都在 content_top.php文件中调用。 你指定的布局页会调用这四个文件 ,所以就会调用你设定的模块了

    Content Top 核心内容我加了注释 代码如下:

        <?php 
        class ControllerCommonContentTop extends Controller {
           protected function index() {
              $this->load->model('design/layout');
              $this->load->model('catalog/category');
              $this->load->model('catalog/product');
              $this->load->model('catalog/information');
              
              if (isset($this->request->get['route'])) {
                 $route = (string)$this->request->get['route'];
              } else {
                 $route = 'common/home';
              }
              
              $layout_id = 0;
              
              if ($route == 'product/category' && isset($this->request->get['path'])) {
                 $path = explode('_', (string)$this->request->get['path']);
                    
                 $layout_id = $this->model_catalog_category->getCategoryLayoutId(end($path));         
              }
              
              if ($route == 'product/product' && isset($this->request->get['product_id'])) {
                 $layout_id = $this->model_catalog_product->getProductLayoutId($this->request->get['product_id']);
              }
              
              if ($route == 'information/information' && isset($this->request->get['information_id'])) {
                 $layout_id = $this->model_catalog_information->getInformationLayoutId($this->request->get['information_id']);
              }
              
              if (!$layout_id) {
                 $layout_id = $this->model_design_layout->getLayout($route);
              }
                    
              if (!$layout_id) {
                 $layout_id = $this->config->get('config_layout_id');
              }
    
              $module_data = array();
              
              //加载extension model
              $this->load->model('setting/extension');
              
              //读取所有安装的模块
              $extensions = $this->model_setting_extension->getExtensions('module');      
              
              foreach ($extensions as $extension) {
                 //读出每个模块的参数配置      模块参数是放到setting表中的   setting表中所有的数据在初始化时候就全读到config类里了 所有这里不需要读数据库
                 $modules = $this->config->get($extension['code'] . '_module');
                 
                 if ($modules) {
                    foreach ($modules as $module) {
                       //过滤掉不是content_top的模块
                       if ($module['layout_id'] == $layout_id && $module['position'] == 'content_top' && $module['status']) {
                          $module_data[] = array(
                             'code'       => $extension['code'],
                             'setting'    => $module,
                             'sort_order' => $module['sort_order']
                          );            
                       }
                    }
                 }
              }
              
              $sort_order = array();
            
              foreach ($module_data as $key => $value) {
                    $sort_order[$key] = $value['sort_order'];
               }
              //排序  这里大家明白了吧 排序在在整个位置排序 所有模块按sort_order排序 并不是每个模块单独排序!  这里大家一定要主要不然就会出乱子了!
              array_multisort($sort_order, SORT_ASC, $module_data);
              
              $this->data['modules'] = array();
              
              //$module_data里现在放的就是 content_top里所有的模块了 循环调用他们的控制器  就是module里模块对应的控制器  $module['setting']作为参数传入
              foreach ($module_data as $module) {
                 //module 返回的html代码
                 $module = $this->getChild('module/' . $module['code'], $module['setting']);
                 
                 if ($module) {
                    $this->data['modules'][] = $module;
                 }
              }
    
              //加载content_top的模板 模板很代码非常简单 就是循环输出  $module  也就是模块返回的html代码
              if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/common/content_top.tpl')) {
                 $this->template = $this->config->get('config_template') . '/template/common/content_top.tpl';
              } else {
                 $this->template = 'default/template/common/content_top.tpl';
              }
                                
              $this->render();
           }
        }
        ?>


    最后总结下 因为模块参数是放到setting表中的所以后台存的时候不需要设置模型 用setting的模型就可以了 前台setting数据会在OC初始化的时候就读入config类里边了 所以连加载setting模型都省了 。另外排序的有效范围是按位置来分的, 比如content Top中所有的模块实例排序,并不是模块实例间排序!

    这样是不是来龙去脉都打通了! 再设计模块就会很轻松了吧 。

  • 相关阅读:
    MapReduce计算之——hadoop中的Hello World
    hadoop命令运行,去除:WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform 警告
    Centos6.10安装tomcat
    Linux中脚本
    R数据可视化手册学习——条形图
    R数据可视化手册学习简单的绘制常见的图形
    一个将任意字符或字符串按位转化为整数的方法
    三级模式两级映像
    天热无聊,用C语言函数指针实现的小函数^_^
    Oracle内存学习笔记
  • 原文地址:https://www.cnblogs.com/mssql8/p/3832715.html
Copyright © 2011-2022 走看看