Mon

03

Nov

2008

Did you know? Overrides are not just for HTML!

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).

24 Votes

11 Comments

Feed
  1. Thanks Anthony this is really cool stuff.

    Nick
  2. Thanks Anthony for this information.
    I tested the HTML part earlier and it worked well. Just have to try this now.
  3. Interesting article indeed.

    While I'm an enthousiast of extensibility, I'm surprised that this method presented is part of the official 1.5 API...

    I didn't think that it would be "safe" to override a joomla class by replacing it completely, without being able to inherit from it, like in usual OOP...

    It limits such overrides to only one extension, and in addition, as you well explained about updates, it is programmed hassles for upgrades, which could affect other extensions than the non-updated one...

    Maybe that could be improved in 1.6 using php5 class extensions/methods overrides with normal parent calls ?
  4. Thanks for this information.
    I would test the HTML part and check whether it works well at me. Just have to try this now.
  5. thank you for the useful info ;)
    is there a way to verride modules too?
  6. Hello

    Views overriding is working well for me but I wasn't able to overide models.

    What should be the right path in the template/html folder to use models overriding please ?

    Regards.
  7. I'd love to know how to do what you are talking about, but cannot quite grasp your 'So how do we do this?' section.

    For example I am using sectionex to give me a list of all articles in a category. I have hacked it so it just displays them by date rather than by category but this had to be done in the model. I also added pagination (via model changes and template overrides).

    I'd really like to know how to add the model file to my template so that any updates to section ex don't stop it working how I want.

    But I cannot understand how to add the override to my template override file :-(

    Any extra help much appreciated
  8. I don't understand like Niko how override the model or the controller !!!
    can you give us the path and/or a complete howto to do what you explain.
    i am very sorry but i try to find this on Google, but anybody talk about that...:'(
  9. This article makes no sense. What file do we put this in, how do we modify it to use it in another component or a module?
  10. Well, this is very sensitive to Joomla version. It's really override *replacements*, not extensions/inheritances like you would prefer much more to have. if you load your class instead of joomla's it has to be named same, so no way to load joomla's. It's just calling for support trouble in the long term, imho. Not recommending to use that.

    Plus you can override only once.

    Making this unplaned side-effect of the Joomla loader an "official API" through this blog makes matters worse.

    Hope Joomla 1.6 will have a better way. ;-)
  11. Hello Anthony
    It sounds good, even though version compatibility and security could be issues. I tried to implement it on a Joomla! 1.5.13, trying to override com_content same as you did... I tried a few things and it does not seem to override anything... Should it still work?

    copied com_content under /plugins/system/comcontentoverride
    I require_once the controller.php file
    Any idea? I'll look at template overriding... I do not really like it... have to implement for all templates :-(

    Thank you!
    Florian

Add Comment


    • >:o
    • :-[
    • :'(
    • :-(
    • :-D
    • :-*
    • :-)
    • :P
    • :\
    • 8-)
    • ;-)