1
\$\begingroup\$

Though I have heard about the magic method __autload, I still prefer to use this code:

function autoload($array)
{
    foreach ($array as $value) 
    {
        switch ($value) 
        {
            case 'database' :
                include ROOT_DIR.'/core/database.php';
                break ;
            case 'user' :
                include ROOT_DIR.'/core/user_class.php';
                break ;
            case 'error_handler' :
                include ROOT_DIR.'/core/error_class.php';
                break ;
            case 'template' :
                include ROOT_DIR.'/template/rain.tpl.class.php';
                break ;
            case 'email' :
                include ROOT_DIR.'/core/email_class.php';
                break ;
        }
    }
}

I'm not exactly sure if this is a good option. Should I switch to the magic method __autoload or keep using my simple switch case? If you propose that I need to use the magic method instead, is it due to a performance-wise factor? If not, why are you suggesting it?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ For reference, this wouldn't be nearly as messy if you stuck to a naming convention. You could easily handle just the odd cases, and let everything else be handled by code that understands your naming scheme. Course, at that point, you're about 80% of the way to a true autoloader anyway... \$\endgroup\$
    – cHao
    Dec 4, 2013 at 23:03
  • 1
    \$\begingroup\$ Also, no one uses __autoload directly anymore. You can (and should!) use spl_autoload_register to set up class autoloaders. Among other things, it lets you have more than one. \$\endgroup\$
    – cHao
    Dec 4, 2013 at 23:10
  • \$\begingroup\$ @cHao Thank you very much, i'll look into spl_autoload .. \$\endgroup\$
    – DriverBoy
    Dec 5, 2013 at 10:21

2 Answers 2

3
\$\begingroup\$

It depends if this is for OOP or procedural code. I am assuming OOP as you use class in some of your file names.

Procedural

If this is for procedural code then it should be renamed to load as there is nothing auto about it (see the OOP review).

OOP

If this is for OOP then it is not a good option. spl_autoload_register to register a standard autoload function is better.

Your Solution

  • There is a hardcoded entry that needs to be maintained for each class that you want to include. This does not scale well with hundreds or thousands of entries to look through.
  • If the value is not recognized you ignore it silently because you don't have a default entry in your switch statement.
  • You have to manually autoload the classes that you want (this takes the auto out of autoload).

Advantages of spl_autoload_register

  • spl_autoload_register is a true automatic loader.

    // We just need one call to register an autoload function, this registers the
    // autoloading for the lifetime of the program.
    spl_autoload_register();
    $exampleObject = new Example_Object;
    
    // In the file autoloaded for class Example_Object:
    class Example_Object
    {
        // Type hinting works to load the class for Another_Object.
        public exampleMethod(Another_Object $another)
        {
            // Autoloading works here too.
            $lastObject = new Last_Object;
        }
    }
    

The autoloader only needs to be registered once and continues to load files for classes right throughout the program.

  • A stack of autoload functions can be provided allowing for flexibility in the logic used to load classes.
  • Because files are loaded lazily only what is required is loaded no matter how much you edit the other files.
  • Using logic to load your class files helps you to organize them logically. It makes your logic simpler if you name your class files logically. This helps when you have hundreds or thousands of files that have been named in a consistent manner.

What not to use an autoloader for

An autoloader is for loading the file needed to define a class. You should not use it to load functions or templates. These should still be included manually.

\$\endgroup\$
0
1
\$\begingroup\$

I think there is merit in this approach for reasons I'll not go into. Instead I'll simply share the core workings of my "magic" class:

<?php
class Magic{
    /** INSTANTIATION
     *
     *      Define the paths to the classes
     */
        public $paths;
        public function __construct(){
            // Define our paths
            $this->paths = array(
                'one'   => dirname(__FILE__) . '/one.php',
                'two'   => dirname(__FILE__) . '/two.php',
                'three' => dirname(__FILE__) . '/three.php'
            );
        }
    /** __GET :: MAGIC METHOD
     *
     *      PHP hits this when trying to access a non-existent classes
     *
     *      We can use it to "autoload" and insantiate on-demand
     */
        public function __get($name){
            // Do we have a path defined?
            if(isset($this->paths[$name])){
                // Hotload the library...
                require_once($this->paths[$name]);
                // What to do?
                if(class_exists($name)){
                    // Instantiate the class
                    $this->$name = new $name($this);
                    return $this->$name;
                }
            }
            // Assume the worst
            return false;
        }
}
$magic = new Magic();

// Usage
$magic->one->stuff();
$magic->two->methods();
$magic->three();

You should be able to deduce that the moment you request an object, the __get magic method is called, at this point we load and instantiate the class making it instantly available. For me this is desirable as I store settings in the Magic object which can be used by the loaded classes during creation.

I too have never been overly keen on using spl_autoload_register; but then I'm guilty of writing tightly coupled code. These are my faults and I do well to be aware of them!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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