Object oriented components , any plan?

106 views
Skip to first unread message

Duccio Gasparri

unread,
Apr 17, 2012, 2:40:09 PM4/17/12
to joomla-...@googlegroups.com
Hi folks,

I've recently "reverse engineered" the way Joomla loads components (so the JSite and JComponentHelper classes), and noticed that if components are now fully structured and object oriented (controllers, views, models, and so on), the loading and execution is still done the old-fashioned way: require_once $componentFile; Everything else is structured and OO, so that way of loading them is quite an absurdity. I have a few ideas on how to improve it and mantain nevertheless the backward compatibility, starting from JControllerHelper::executeComponent that could become something like:

    //file libraries/joomla/application/component/helper.php
    /**
     * Execute the component.
     *
     * @param string $path           The component path.
     * @param string $baseClass  The base class of the component (ComponentController)
     *
     * @return string The component output
     *
     * @since 11.1
     */
    protected static function executeComponent($path, $baseClass)
    {
        ob_start();
        require_once $path;
        if(class_exists($baseClass)) {  //Compatible with older components
            //Could return self or directly the controller
            $controller = $baseClass::factory();
            /* @var JController $controller */
            $controller->execute();
            $controller->redirect();
        }
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }



If we want to avoid the multiplication of classes (and we want to avoid instantiating useless ones as well), I believe the best solution is to put an "ExampleController extends JController" inside the com_example/example.php, and add a static factory() method to JController (for more detail on how I tought to approach the OO component loading). This factory method should instantiate directly the specific controller, and return it. Part of this can already be taken from the JController::getInstance() (which is now quite a mess, because (my humble opinion) getInstance is not intended to choose the class to instantiate, but just to instantiate the called class and keep an instance of it stored). I'm willing to put up some time to code it, but since it's a quite important change and requires to "touch" a few parts of the library (mainly JControllerHelper, JController), I wanted to know if you had already thought about it, and if you can notice/suggest pros or cons about this or other implementations.

Any idea on that?

Duccio

Sam Moffatt

unread,
Apr 17, 2012, 4:03:04 PM4/17/12
to joomla-...@googlegroups.com
I think you should start on the platform list since there have been
discussions on replacing the present MVC implementation with a cleaner
version.

Cheers,

Sam Moffatt
http://pasamio.id.au

> --
> You received this message because you are subscribed to the Google Groups
> "Joomla! CMS Development" group.
> To view this discussion on the web, visit
> https://groups.google.com/d/msg/joomla-dev-cms/-/Ibxga2RxHI8J.
> To post to this group, send an email to joomla-...@googlegroups.com.
> To unsubscribe from this group, send email to
> joomla-dev-cm...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/joomla-dev-cms?hl=en-GB.

Rouven Weßling

unread,
Apr 17, 2012, 4:08:15 PM4/17/12
to joomla-...@googlegroups.com
That has already happened. However I don't think that impacts Duccio's proposal. JComponentHelper is eventually going to leave the platform anyways. (it will be moved to the CMS than).

What I'm wondering is, if components currently do anything else in their main file to bootstap the extension that couldn't be done in controllers constructor?

Also I wonder if there's a backward compatibility impact.

Otherwise I quite like the idea, it could help reduce the amount of essentially duplicate code quite a bit.

Rouven

Duccio Gasparri

unread,
Apr 17, 2012, 5:58:34 PM4/17/12
to joomla-...@googlegroups.com
Right now (Joomla 2.5 and Platform 1.4), that is still clearly in the CMS, that's why I posted it here. There are bits and pieces in the nightly build (https://github.com/joomla/joomla-platform/blob/staging/libraries/joomla/controller/controller.php), and I do see a sense of moving it to the platform (a platform without a MCV? would it make sense?) but right now it is still a work in progress, and anyway when the structure of the code is good, it can be moved quite easily.

As far as I can tell, there's no backward compatibility issue. With the proper check (the best I can think of is the existence of the base class ExampleController after the require), it just loads "the php4 way" transparently.

As for components doind other things in the main file, that's a very good question. It must stay in the main file so one doesn't have to duplicate it in each controller. As (ideally) the base class ExampleController is not instantiated, I guess it could be a onBeforeFactory() and/or onAfterFactory() methods called statically by the factory() method. That way if I want for example to define a constant or do other tasks, I can put them in the base class without changing the factory (unless I need to, of course). OR, other option, it can be put in the constructor of ExampleController, and the single controllers would extend that instead of JController (ExampleController would be an extension of JController, so its methods and properties would be inherited anyway).

Duccio

>> To post to this group, send an email to joomla-dev-cms@googlegroups.com.


>> To unsubscribe from this group, send email to

>> joomla-dev-cms+unsubscribe@googlegroups.com.


>> For more options, visit this group at
>> http://groups.google.com/group/joomla-dev-cms?hl=en-GB.
>
> --
> You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.

> To post to this group, send an email to joomla-dev-cms@googlegroups.com.
> To unsubscribe from this group, send email to joomla-dev-cms+unsubscribe@googlegroups.com.

Mark Dexter

unread,
Apr 17, 2012, 7:24:56 PM4/17/12
to joomla-...@googlegroups.com
I don't know if this is directly related or not, but it seems that we should try to get rid of as many require_once statements as possible and replace them with either jimport, JRegister::load, the auto loader, or some other method that uses the faster PHP load. My understanding is that require_once can cause performance issues in some environments, and in most cases (loading classes, for example) we don't need it.

Mark

To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-cms/-/X-1HAEXS-bYJ.

To post to this group, send an email to joomla-...@googlegroups.com.
To unsubscribe from this group, send email to joomla-dev-cm...@googlegroups.com.

Adam Stephen Docherty

unread,
Apr 17, 2012, 8:30:49 PM4/17/12
to Joomla! CMS Development
Mark,

Could you explain a little about what you mean by the "faster PHP
load", I have not heard of this and I would be interested if you could
point me in the right direction.

Thanks!

On Apr 17, 8:24 pm, Mark Dexter <dextercow...@gmail.com> wrote:
> I don't know if this is directly related or not, but it seems that we
> should try to get rid of as many require_once statements as possible and
> replace them with either jimport, JRegister::load, the auto loader, or some
> other method that uses the faster PHP load. My understanding is that
> require_once can cause performance issues in some environments, and in most
> cases (loading classes, for example) we don't need it.
>
> Mark
>
> On Tue, Apr 17, 2012 at 2:58 PM, Duccio Gasparri
> <duccio.gaspa...@gmail.com>wrote:
>
>
>
>
>
>
>
> > Right now (Joomla 2.5 and Platform 1.4), that is still clearly in the CMS,
> > that's why I posted it here. There are bits and pieces in the nightly build
> > (
> >https://github.com/joomla/joomla-platform/blob/staging/libraries/joom...),
> >> >> from JControllerHelper::**executeComponent that could become
> >> something like:
>
> >> >>     //file libraries/joomla/application/**component/helper.php
> >> >>https://groups.google.com/d/**msg/joomla-dev-cms/-/**Ibxga2RxHI8J<https://groups.google.com/d/msg/joomla-dev-cms/-/Ibxga2RxHI8J>
> >> .
> >> >> To post to this group, send an email to joomla-dev-cms@googlegroups.**
> >> com <joomla-...@googlegroups.com>.
> >> >> To unsubscribe from this group, send email to
> >> >> joomla-dev-cms+unsubscribe@**googlegroups.com<joomla-dev-cms%2Bunsu...@googlegroups.com>
> >> .
> >> >> For more options, visit this group at
> >> >>http://groups.google.com/**group/joomla-dev-cms?hl=en-GB<http://groups.google.com/group/joomla-dev-cms?hl=en-GB>
> >> .
>
> >> > --
> >> > You received this message because you are subscribed to the Google
> >> Groups "Joomla! CMS Development" group.
> >> > To post to this group, send an email to joomla-dev-cms@googlegroups.**
> >> com <joomla-...@googlegroups.com>.
> >> > To unsubscribe from this group, send email to
> >> joomla-dev-cms+unsubscribe@**googlegroups.com<joomla-dev-cms%2Bunsu...@googlegroups.com>
> >> .
> >> > For more options, visit this group athttp://groups.google.com/**
> >> group/joomla-dev-cms?hl=en-GB<http://groups.google.com/group/joomla-dev-cms?hl=en-GB>
> >> .

Mark Dexter

unread,
Apr 17, 2012, 8:38:43 PM4/17/12
to joomla-...@googlegroups.com
Hi Adam. If I understand this correctly, the magic happens with the PHP spl_autoload_register command -- for example, in JLoader::setup(). I believe this allows PHP to load the class only when it is called and is faster than require_once or include_once.

The disadvantage of using JLoader::register() is that you need to know the class name in advance, which you don't need to know with require_once.

Hope that helps. Mark

Adam Stephen Docherty

unread,
Apr 17, 2012, 8:54:25 PM4/17/12
to Joomla! CMS Development
Thanks Mark, I will definitely be taking a look at this.

Duccio Gasparri

unread,
Apr 19, 2012, 4:33:48 AM4/19/12
to joomla-...@googlegroups.com
Mark, what you say is definitely true but I wouldn't apply it to this specific case because using JLoader would probably break backward compatibility with older components, that's why I opted for mantaining the require_once (which I hate).

Duccio

elin

unread,
Apr 19, 2012, 8:49:24 AM4/19/12
to joomla-...@googlegroups.com
The scary one to look at is com_media in the front end, someone needs to take up refactoring that one....

In com_banners we have ...

$controller->execute(JRequest::getVar('task', 'click'));

Also  ... we are requiring all these specific helpers by name but why not just assume that if there is a helper in the right place it should be loaded or even better load it when it is actually needed?

Elin

>> To post to this group, send an email to joomla-dev-cms@googlegroups.com.


>> To unsubscribe from this group, send email to


>> For more options, visit this group at
>> http://groups.google.com/group/joomla-dev-cms?hl=en-GB.
>
> --
> You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.

> To post to this group, send an email to joomla-dev-cms@googlegroups.com.
> To unsubscribe from this group, send email to joomla-dev-cms+unsubscribe@googlegroups.com.

Duccio Gasparri

unread,
Apr 19, 2012, 10:19:23 AM4/19/12
to joomla-...@googlegroups.com
I did pull 193 (about JController::factory) and 194 (componentHelper) https://github.com/joomla/joomla-cms/pull/193 and https://github.com/joomla/joomla-cms/pull/194 if you want to take a look.


The real issue with com_media is from line 43 to 75 of media.php:

$cmd    = JRequest::getCmd('task', null);

if (strpos($cmd, '.') != false) {
[...]

// Set the name for the controller and instantiate it
$controllerClass = 'MediaController'.ucfirst($controllerName);

if (class_exists($controllerClass)) {
    $controller = new $controllerClass();
}
else {
    JError::raiseError(500, JText::_('JERROR_INVALID_CONTROLLER_CLASS'));
}


because it does exactly what the new renderComponent would do. It is about simplifying it rather than recoding it, but before moving forward with all the libraries I'd like to hear if the pulls I did on GitHub are in the right direction.

I'm stuck in those two issues:

1) do we want to mantain both com_example/example.php and com_example/controller.php files? Should we decide to merge it in one single file? (controller.php? example.php, which would be the standard one?)
2) for the components that do other stuff, where do we want to put it? In the base file as they are now, they would be loaded so it is not an issue to "leave them there". But looking forward, let's try to find a better place.

There are two kinds of stuff that could be done at startup, the general bootstrapping (such as defining constants) which should be done only once and maybe called statically, and an init() for (for example) checking if the user is authorized, which should be more associated with execute than to __construct().

Four options come to my mind:
       a) create hooks inside JController (onBootstrap, onBeforeFactory and onAfterFactory, onBeforeExecute and onAfterExecute)
       b) similar to the previous one, leave people free to overload the factory and __construct methods without creating a hook  (function factory(..) { /* ... do your stufff */ $instance = parent::factory(); /* do other stuff */ }
       c) create a init() method to be called right after __construct(); so that if I want to just set a couple of variable, I can just define this init() function
       d) create a static bootstrap() method to be called once by factory() or by construct()

The more we add methods, the less clear the code will be to understand and to extend/change so we must be careful. Point c can be just done overloading __construct() and point d by overloading factory and contructor, but init and bootstrap are quite easy to remember and I don't see them as big issues.

I have no clue on what could be the best option...
Reply all
Reply to author
Forward
0 new messages