The Joomla! Community Portal ™

Mon

03

Nov

2008

Did you know? Overrides are not just for HTML!
Written by Anthony Ferrara   
Monday, 03 November 2008 00:12

Arguably, one of the greatest features of Joomla! 1.5 is the ability to override nearly every single piece of HTML output that it produces.  What most people don't realize, is that you can do the same thing with all the core components' classes!  You can override controllers, models and views!  What does this mean for you?  You almost never need to actually modify the core of Joomla!  All you need to override a controller, model or view (or multiple), is a simple plugin!

What can you override?

Well, you can directly override a controller, a model, and a view class (view layouts cannot be overridden in this manner, but can be using the template).  This leaves the problem that what do you do for routers?  Well, you can attack router build and parse rules to alter the routing behavior!  So in short, you can override anything in Joomla, except the application class (JSite, JAdministrator, etc), plugins, modules, and certain includes that happen before the first plugin fires (anything loaded before onAfterInitialize).  Anything else can be overridden!

How is this possible?

Very simple.  If you look at JController and JModel, you'll notice that the code that instantiates the controller, model and view, it has if(!class_exists($class)) wrapped around the code used to load the respective class.  What this means is that if you load your own class (of the same name), it will use that instead of the core class.  Imagine the possibilities!

If you didn't already know, you can also add views to any component by simply adding the appropriate view folder (and files) to the component. Combine the adding of new views with overriding existing views, and you can change EVERYTHING in a component! So the system really is incredibly flexible.

So, how do we do this?

Well, in order to provide any semblance of performance, you'll only want to load the class if it's going to be used.  Since the code uses require to load the class, jimport won't work.  So how do you determine if it's going to be used?  Simple, check the option variable in an onAfterRoute plugin event.  Here's a basic concept (override the com_content controller):

 
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');
          }
      }
 
 }
 

Are there limitations?

Yes. Unfortunately, there's no way as of yet to override parts of a class. You must override the entire class. This means, that you need to copy the entire class (but, it prevents changes from being deleted on upgrade)! But, be aware that any changes in new versions of Joomla should be merged back into this override (if there's a security fix in that particular file, the fix will be overridden until the override is changed).