5

There is one class called JLoader which has auto loading techniques for loading the library packages.

Why do we need some class for loading when we already have Composer autoloading?

What is this registerPrefix in the JLoader class?

6

My understanding of autoloading is fairly rudimentary but since this has 4 votes and no answers I think I will give it a shot. Please more knowledgeable types add corrections or a better answer etc.

Short Answer

The composer autoloader is used to autoload the php packages in libraries/vendor. The JLoader autoloaders (it can queue up a few) autoload everything else except for the core FOF autoloader and any other autoloaders that any extensions register. The composer autoloader is not the most flexible system to modify at runtime and there are a number of benefits to queuing multiple autoloaders rather than a single one that implements both cached and runtime path finding strategies.

Long Answer

PHP provides a simple way to deal with loading classes without having to use include or require statements - autoloaders! They work by allowing a 'class not found' error to trigger any registered autoloaders to find and load the class before continuing with the process. This allows you to not have to write require statements everywhere, but much more importantly, it allows your PHP to load only the classes that get called, not all the classes that might get called.

PHP Doc on registering autoloaders

https://www.php.net/manual/en/function.spl-autoload-register.php

More than one autoloader can be registered, and if an autoloader doesn't know where a class is, the next autoloader in the queue can have a go and so on and so on...

Autoloaders are not magical, they each have to implement a strategy of finding the file with the called class in it. The composer autoloader has several strategies that it uses, but there are two basic ones: PSR-4 (where each package must follow a set directory structure and name spacing schema) and the class map (used to add legacy code matching some other structure). The full list is here:

https://getcomposer.org/doc/04-schema.md

But in general composer has all of its strategies for turning class names and namespaces into paths already cached up and ready prior to runtime so that it can do it as fast as possible. A bunch of joomla vendor packages are included using composer already, and you can see them all in /libraries/vendor/joomla/

The Joomla autoloader, implemented in the JLoader class, is more focussed on loading not only joomla application code, but also code required by all the core and third party extensions. The JLoader also has a bunch of strategies for finding classes including the register prefix method.

https://api.joomla.org/cms-3/classes/JLoader.html#method_registerPrefix

registerPrefix allows for classes with no namespacing to simple find classes that start with some characters to look in a path. There are already plenty of examples of using JLoader registerPrefix, so let's write an autoloader from scratch using a similar strategy.

Let's say in the entry file of your custom component - you wanted to write your own classic MVC PHP without using the Joomla component code, well then you could add your own autoloader only when you component is called.

Assuming that your prefix is Xyz, and your classes are arranged as follows:

/components/com_example/views/XyzView.php
/components/com_example/views/XyzExampleView.php
/components/com_example/models/XyzModel.php
/components/com_example/models/XyzExampleModel.php

And XyzExampleView.php would of course contain:

Class XyzExampleView extends XyzView {/* real code */}

In the component entry file before launching some kind of router/front controller etc, you would add the following kind of autoloader:

function autoload_class($class) {
    if(strpos($class,'Xyz') === false){
        // the called class is not ours, so let this through to the next autoloader in the queue
        return;
    } elseif(strpos($class,'View') !== false){
        include 'views/' . $class . '.php';
    } elseif (strpos($class,'Controller') !== false){
        include 'controllers/' . $class . '.php';
    } elseif (strpos($class,'Model') !== false){
        include 'models/' . $class . '.php';
    } else {
        include 'helpers/' . $class . '.php';
    }
}
spl_autoload_register('autoload_class');

The above makes a very big assumption that no classes by other people will start with Xyz and follows the very strict rule that every class you do want autoloaded will start with Xyz. But if that is safe enough then the above is ready to go.

  • 1
    When you have a really good hammer (Composer) everything tends to look like a nail. But things like screws exist, so we need screwdrivers (non-Composer approaches to class loading). – Arlen Aug 13 at 14:27
4

James did a good differentiator between the composer autoloader and JLoader. I think the other thing that your missing here is that JLoader massively predates composer existing (and even when composer did exist it wasn't until the stable release it really became usable on shared hosting fully).

Slowly over time we will move things towards the composer autoloader in core. For example in Joomla 4.0 all the core libraries are moving across to it. However alongside this it has to be done in tandem with a move from lots of our core factories to use dependency injection from the old static methods we used in JFactory. Before several major components in the ecosystem actually overrode the JLoader mappings to inject their own classes (a good example is several MailChimp extensions overriding the JMail class).

registerPrefix dates from a time before namespaces existed in PHP. As a result it's something totally custom we built for Joomla. Now namespaces exist we've started the move (and therefore away from registerPrefix) with the core libraries being namespaced in Joomla 3.8. But basically rather than a namespace segment corresponding to a directory, you have say /folder/subfolder/class corresponding to a class of PrefixFolderSubfolderClass

Hopefully this gives some historical background beyond the technical details already mentioned!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.