1
\$\begingroup\$

I don't understand the concept of autoloaders, other than the bare minimum, which is that to load a class file when the class is being called. Or as the PHP manual cites it, to avoid having to require multiple time.

I get that, but what I don't understand is the complexity behind almost all the autoloaders which I sought to learn some things from. It's almost impossible to understand what goes on behind the scenes.

Just to understand it a bit more with your help, I made a simple autoloader as you can see below:

class Autoloader
{
    private $pathToClass; 

    //register the path
    function __construct($pathToClass)
    {
        $this->pathToClass = $pathToClass; 
    }

    //load the file
    public function load($class)
    {

        // expload the namespaces ex: foo\bar\tar array(foo, bar, tar)
        $explode = explode('\\', $class); 

        //get the last exploaded string and append .php so it becomes tar.php
        $class = $explode[count($explode) - 1].'.php'; 

        // required tar.php in the path it is found ex:
        // require '/foo/bar/tar.php' in lowecase to avoid windows/unix conflict
        if(file_exists(strtolower($this->pathToClass.$class))){
             require strtolower($this->pathToClass.$class);

            return true; 
        }

        return false; 
    }   

    // autoload
    public function register()
    {
        spl_autoload_register([$this, 'load']);
    }
}

The class explains itself. It does work, and I just would like to know what I am missing? As you can see, it is the most basic autoloader. What would be the next most important thing you would add to it?

Here is how it is instantiated:

$myLibLoader = new Autoloader(__DIR__.'/foo/bar/');
$myLibLoader->register();


$foo =  new foo();
\$\endgroup\$
3
\$\begingroup\$

Comments on your code

  • The access modifier for your constructor is missing.

    function __construct...
    public function __construct
    

    Although no specified access modifier on methods means that PHP chooses public automatically (see PHP docs), I would add it for consistency.

  • Your autoloader does not cope with namespaces. You might want to read PSR-0, a specification stating how autoloaders should cope with namespaces, folders and filenames.

  • Do not add random newlines.

    public function load($class)
    {
    
        // expload the namespaces ex: foo\bar\tar array(foo, bar, tar)
    
    public function load($class)
    {
        // expload the namespaces ex: foo\bar\tar array(foo, bar, tar)
    
  • Do not add random spaces in comments.

    // expload the namespaces ex: foo\bar\tar array(foo, bar, tar)
    //get the last exploaded string and append .php so it becomes tar.php
    

    Be consistent! I suggest using a space after //.

  • Be specific in variable names. $pathToClass lets me think that the string points to a specific class file. It does however point to a directory containing class files. I suggest using $classDir. $class is also an edge case since it does contain more than a single class name.

  • You don't need explode if you only wish to extract the class name. Use strrpos():

    $classFilename = substr($class, strrpos($class, '\\') + 1) . '.php';
    
  • Don't apply strtolower two times. Just save the result in a temporary variable. It makes your code DRY.

  • Since you declare pathToClass private anyway, consider marking the class final. Some arguments are provided in an article Final should be Default for Classes in Java (the same principles not only apply to Java, but also to many other languages including PHP).

  • Mark your load method private. It's an implementation detail, which shouldn't be accessible from outside the class.

  • Your load method is not required to return a boolean value. Returning true or false is not bad per se, maybe you will want to encapsulate the autoloading mechanism further and throw exceptions depending on the return value.


Elaborating on the PSR-0 specification

The spec defines mandatory requirements your autoloader must fulfill.

They provide example inputs your autoloader must accept:

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

Roughly speaking, your code is missing the following aspects:

  • Taking the namespace into account and using it to build a directory hierarchy.
  • Transforming underscores in class names to a directory hierarchy as well.
\$\endgroup\$
7
  • \$\begingroup\$ First thanks for the answer, but when I asked the question about improving, I was not referring to naming inconsistencies, comments or about access modifiers. I was more asking about what is the next step to make this autoloader more trivial than it is. You did bring an interesting note about the PSR though. I don't understand much about the PSR (If I did, I wouldn't be using this autoloader) so, it would be nice if you could explain what this class is missing from the PSR \$\endgroup\$ – robue-a7119895 Aug 3 '14 at 20:33
  • \$\begingroup\$ *less trivial than it is :) \$\endgroup\$ – robue-a7119895 Aug 3 '14 at 20:41
  • \$\begingroup\$ @CONtext Well, it's always good to improve one's code as well :) I did elaborate a bit on PSR-0, please see my update. \$\endgroup\$ – ComFreek Aug 3 '14 at 20:54
  • \$\begingroup\$ Ok, I got the second point. Seems pretty straight forward. I should use DIRECTORY_SEPERATOR to make my autoloader namespace friendly. As some frameworks use underscore _ and others use ` But the first point is tough to understand. Does it mean if I am loading a class as $foo = new foo\bar\tar\register` then, that class register or register.php should be stored inside `foo\bar\tar` folder? should the full namespace be identical to the folder structure? \$\endgroup\$ – robue-a7119895 Aug 3 '14 at 21:04
  • \$\begingroup\$ @CONtext Exactly, the qualifier foo\bar\tar\register requires you (according to PSR-0) to load register.php from the path foo/bar/tar. Note that underscores only play a role in class names. They remain in package names as is. \$\endgroup\$ – ComFreek Aug 3 '14 at 21:07

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.