模块与内容框

osCommerce V3 可以在后台直接设置所有模块、内容框的参数,甚至可以自定义它们的显示位置, 以及控制它们在哪些页面才生效。

下面是系统默认的所有功能模块:

以及它们的位置参数:

下面是系统默认的所有内容框:

以及它们的位置设置:

模块与内容框的位置设置参数是一样的,包含了以下几个参数:

  • Pages:模块、内容框将显示在哪些页面,如果为“”表示将出现在所有页面,如果为 “products/”表示将出现在所有归于 products.php 主文件的页面,例如:products/info(产品介绍)、products/new(新产品页面,URL:products.php?new)等,但如果设置为“products/info”, 那么此模块将只显示在一个页面里,也就是产品介绍页面
  • Page Specific:指定此模块/内容框为页面独占,如果设置了此参数,则在同一页面同一类(同一位置,如左边栏、右边栏)的其它模块或内容框将不会显示,除非那个模块/内容框也设置为页面独占
  • Group:显示的位置,默认情况下内容框只有“left”和“right”两个选项可选,left即为左边栏、right 为右边栏;功能模块也只有两个可选:“before”、“after”,before 即在主内容前,after为在主内容后。如果对页面的架构有更高的要求,可以命名自定义的位置
  • Sort Order:在同一类位置中的显示次序

提示:

如果需要自定义显示位置,不仅需要在模块/内容框里设置位置的名称,而且需要在模板文件(如 templates/default.php)里增加相应的代码,以便能够将它们显示在特定的位置上。

显示与位置

在主内容之前显示功能模块 templates/default.php[55]

if ($osC_Template->hasPageContentModules()) { // hasPageContentModules方法总返回 True
  foreach ($osC_Services->getCallBeforePageContent() as $service) { // 如果需要在处 理功能模块之前开启的服务,则加载此服务
    $$service[0]->$service[1](); // getCallBeforePageContent方法返回的是二维数组, $service[0]是对象,$service[1]是对象的方法,即需要在处理左边栏之前运行的代码
  }

  foreach ($osC_Template->getContentModules('before') as $box) { // 获取所有类型为 “before”的功能模块类名,所有功能模块继承自 osC_Modules 类
    $osC_Box = new $box();
    $osC_Box->initialize(); // 初始化功能模板,$osC_Box 的内部变量$_content 将被赋予显示 的内容
    if ($osC_Box->hasContent()) { // hasContent是osC_Modules类的一个方法,它检查内部 变量$_content 是否有内容
      if ($osC_Template->getCode() == DEFAULT_TEMPLATE) {
        // 得到了内容后,则需要将其 显示出来,负责这一任务的是功能模块之模板,其保存路径是“ templates/TEMPLATE_NAME/modules/content/MODULE_CODE.php”,其中的 MODULE_CODE 由功能模 块类的$_code 内部变量指定,通过与功能模块名称一致,下面的$osC_Box->getCode()方法便是获得内部变 量$_code 的值
        include('templates/' . $osC_Template->getCode() . '/modules/content/' . $osC_Box->getCode() . '.php');
      } else {
        if (file_exists('templates/' . $osC_Template->getCode() . '/modules/content/' . $osC_Box->getCode() . '.php')) {
          include('templates/' . $osC_Template->getCode() . '/modules/content/' . $osC_Box->getCode() . '.php');
        } else {
          include('templates/' . DEFAULT_TEMPLATE . '/modules/content/' . $osC_Box->getCode() . '.php');
        }
      }
    }

    unset($osC_Box);
  }
}

需要提醒一点:紧跟着这段代码的后面便是我们前面讲到的显示主模块内容(行号:80),所以这段代码生成的内容将显示在主内容前面。

鉴于 osCommerce V3 的模块与内容框可自定义位置是基于其新增的若干个表,所以有必要介绍一 下模块/内容框的加载过程

osC_Modules 类 includes/classes/modules.php[127]

function __construct($group) {
  // 参数有两种,“content”和“boxes”,分别对应模块和内容框, 也就是说系统使用同一个类 osC_Modules 来管理模块和内容框。同时它们都是 osC_Modules 类的子类。
  global $osC_Database, $osC_Template, $osC_Cache;

  $this->_group = $group;

  // 模块和内容框的配置也被缓存起来了,这对性能的提升相当重要
  if ($osC_Cache->read('templates_' . $this->_group . '_layout-' . $osC_Template->getCode() . '-' . $osC_Template->getGroup() . '-' . $osC_Template->getPageContentsFilename())) {
    $data = $osC_Cache->getCache();
  } else {
    $data = array();

    // 首先加载那些独占型的模块/内容框,请注意 SQL 语句中的“page_specific = 1”
    $Qspecific = $osC_Database->query('select b2p.boxes_group, b.code from :table_templates_boxes_to_pages b2p, :table_templates_boxes b, :table_templates t where b2p.templates_id = :templates_id and b2p.page_specific = 1 and b2p.content_page in (:content_page) and b2p.templates_boxes_id = b.id and b.modules_group = :modules_group and b2p.templates_id = t.id order by b2p.boxes_group, b2p.sort_order');
    $Qspecific->bindTable(':table_templates_boxes_to_pages', TABLE_TEMPLATES_BOXES_TO_PAGES);
    $Qspecific->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES);
    $Qspecific->bindTable(':table_templates', TABLE_TEMPLATES);
    $Qspecific->bindInt(':templates_id', $osC_Template->getID()); // 位置同样与模板相关联,这样不同的模板可以做到显示位置不同
    $Qspecific->bindRaw(':content_page', '"*", "' . $osC_Template->getGroup() . '/*", "' . $osC_Template->getGroup() . '/' . substr($osC_Template->getPageContentsFilename(), 0,strrpos($osC_Template->getPageContentsFilename(), '.')) . '"'); // 判断是否在调用页里 出现,这里指定了三种可能性

    $Qspecific->bindValue(':modules_group', $this->_group); // 是模块,还是内容框
    $Qspecific->execute();
    if ($Qspecific->numberOfRows()) {
      while ($Qspecific->next()) {
        $data[$Qspecific->value('boxes_group')][] = $Qspecific->value('code'); // “boxes_group”字段即位置类,“code”字段为识别字
      }
    } else {
      $_data = array(); // 普通加载模式
      $Qmodules = $osC_Database->query('select b2p.boxes_group, b2p.content_page, b.code from :table_templates_boxes_to_pages b2p, :table_templates_boxes b, :table_templates t where b2p.templates_id = :templates_id and b2p.content_page in (:content_page) and b2p.templates_boxes_id = b.id and b.modules_group = :modules_group and b2p.templates_id = t.id order by b2p.boxes_group, b2p.sort_order');
      $Qmodules->bindTable(':table_templates_boxes_to_pages', TABLE_TEMPLATES_BOXES_TO_PAGES);
      $Qmodules->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES);
      $Qmodules->bindTable(':table_templates', TABLE_TEMPLATES);
      $Qmodules->bindInt(':templates_id', $osC_Template->getID());
      $Qmodules->bindRaw(':content_page', '"*", "' . $osC_Template->getGroup() . '/*", "' . $osC_Template->getGroup() . '/' . substr($osC_Template->getPageContentsFilename(), 0, strrpos($osC_Template->getPageContentsFilename(), '.')) . '"');

      $Qmodules->bindValue(':modules_group', $this->_group);
      $Qmodules->execute();
      while ($Qmodules->next()) {
        $_data[$Qmodules->value('boxes_group')][] = array('code' => $Qmodules->value('code'), 'page' => $Qmodules->value('content_page'));// 与独占模式不同,这里多了一个“page”值,其目的用于清除重复数据,见下面的代码
      }

      // 清除重复出现的模块/内容框
      foreach ($_data as $groups => $modules) {
        $clean = array();
        foreach ($modules as $module) {
          if (isset($clean[$module['code']])) {
            if (substr_count($module['page'], '/') > substr_count($clean[$module['code']]['page'], '/')) {
              unset($clean[$module['code']]);
            }
          }
          $clean[$module['code']] = $module;
        }
        $_data[$groups] = $clean;
      }

      foreach ($_data as $groups => $modules) {
        foreach ($modules as $module) {
          $data[$groups][] = $module['code'];
        }
      }
    }

    $osC_Cache->write($data);
  }

  $this->_modules = $data;
}

osC_Template 类的 getContentModules 方法 includes/classes/template.php[318]

function getContentModules($group) {
  if (isset($this->osC_Modules_Content) === false) {
    $this->osC_Modules_Content = new osC_Modules('content'); // 指定要加载功能模块
  }

  return $this->osC_Modules_Content->getGroup($group); //通过调用osC_Modules类的 getGroup 方法实现其功能,通过指定参数$group 来获得指定位置的模块或内容框
}

osC_Modules 类的 getGroup 方法 includes/classes/modules.php[127]

function getGroup($group) {
  $modules = array();
  if (isset($this->_modules[$group])) { // 直接通过内部变量$_modules 数组便可得知是否 存在满足条件的内容
    foreach ($this->_modules[$group] as $module) {
      if (file_exists('includes/modules/' . $this->_group . '/' . $module . '.php')) {
        $class = 'osC_' . ucfirst($this->_group) . '_' . $module; // 类的命名规则

        if (class_exists($class) === false) {
          include('includes/modules/' . $this->_group . '/' . $module . '.php'); // 加载子类,即满足条件的模块/内容框
        }

        $modules[] = $class; // 返回所有类名 }
      }
    }
  }

  return $modules;
}

在这里,于主体内容前如何显示功能模块已经介绍完了。至于如何在主体内容后显示功能模块, 和如何显示左边栏以及右边栏,其过程与我们前面所说的大体一致,所以不再详述,它们的不同之处在于:

  • 主体内容后的功能模块使用“after”做为位置名称
  • 左边栏和右边栏分别使用“left”和“right”做为位置名称
  • 加载内容框使用的是$osC_Template->getBoxModules方法,而非getContentModules方法

results matching ""

    No results matching ""