可以说,Joomla! 1.5最伟大的特性之一是能够覆盖它产生的几乎每一个HTML输出。 大多数人没有意识到的是,你可以对所有核心组件的类做同样的事情! 你可以覆盖控制器、模型和视图! 这意味着什么? 你几乎永远不需要实际修改Joomla!的核心。 覆盖一个控制器、模型或视图(或多个),只需要一个简单的插件!

你可以覆盖什么?

嗯,你可以直接覆盖一个控制器、一个模型和一个视图类(视图布局不能以这种方式覆盖,但可以使用模板)。 这留下了一个问题,那就是你如何处理路由器? 嗯,你可以攻击路由构建和解析规则来改变路由行为! 所以简而言之,你可以覆盖Joomla中的任何东西,除了应用程序类(JSite、JAdministrator等)、插件、模块和第一个插件触发之前的一些包含(onAfterInitialize之前加载的任何内容)。 其他任何东西都可以被覆盖!

这是如何可能的?

非常简单。 如果你看看JController和JModel,你会注意到用于实例化控制器、模型和视图的代码周围有一个if(!class_exists($class))。 这意味着如果你加载了自己的类(相同名称),它会使用那个类而不是核心类。 想象一下可能性!

如果你还不知道,你可以通过简单地向组件添加适当的视图文件夹(和文件)来向任何组件添加视图。结合添加新视图和覆盖现有视图,你可以更改组件中的EVERYTHING!所以这个系统实际上是非常灵活的。

那么,我们如何操作呢?

为了提供任何意义上的性能,您只想在将要使用的时候加载类。由于代码使用require来加载类,jimport将不起作用。那么如何判断它是否会使用呢?很简单,检查onAfterRoute插件事件中的选项变量。以下是一个基本概念(覆盖com_content控制器)

class plgSystemComContentOverride extends JPlugin {

       public function __construct(&$subject, $config = array()) {
          parent::__construct($subject, $config);
      }

      public function onAfterRoute() {
          $app = JFactory::getApplication();
          if('com_content' == JRequest::getCMD('option') && !$app->isAdmin()) {
              require_once(dirname(__FILE__) . DS . 'comcontentoverride' . DS . 'my_content_controller.php');
          }
      }

 }

有局限性吗?

是的。遗憾的是,目前还无法覆盖类的部分内容。您必须覆盖整个类。这意味着,您需要复制整个类(但这可以防止升级时更改被删除)!但是,请注意,Joomla新版本中的任何更改都应该合并回这个覆盖(如果该文件中有安全修复,则修复将被覆盖,直到覆盖被更改)。