Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: how to autoload interfaces and abstracts

I have this autoloader class to autoload classes initially, but now I want to autoload interfaces and abstracts as well.

So I made the change following this answer,

$reflection = new ReflectionClass($class_name);

# Return boolean if it is an interface.
if ($reflection->isInterface())
{
    $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php';
}
else
{
    $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php';

}

I tested it but this autoloader class does not load interfaces at all. Any ideas what I have missed?

For instance, this is my interface file,

interface_methods.php

and its content,

interface methods 
{
    public function delete();
}

Below is my entire this autoloader class.

class autoloader
{
    /**
     * Set the property.
     */
    public $directory;
    public $recursive;

    public function __construct($directory, $recursive = array('search' => 'models') ) 
    {
        # Store the data into the property.
        $this->directory = $directory;
        $this->recursive = $recursive;

        # When using spl_autoload_register() with class methods, it might seem that it can use only public methods, though it can use private/protected methods as well, if registered from inside the class:
        spl_autoload_register(array($this,'get_class'));
    }

    private function get_class($class_name)
    {
        # List all the class directories in the array.
        if ($this->recursive)
        {
            $array_directories =  self::get_recursive_directory($this->directory);
        }
        else
        {
            if (is_array($this->directory)) $array_directories =  $this->directory;
            else $array_directories =  array($this->directory);
        }

        # Determine the class is an interface.
        $reflection = new ReflectionClass($class_name);

        $file_pieces = explode('\\', $class_name);

        # Return boolean if it is an interface.
        if ($reflection->isInterface())
        {
            $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php';
        }
        else
        {
            $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php';

        }

        # Loop the array.
        foreach($array_directories as $path_directory)
        {
            if(file_exists($path_directory.$file_name)) 
            {
                include $path_directory.$file_name;
            } 
        }

    }

    public function get_recursive_directory($directory)
    {
        $iterator = new RecursiveIteratorIterator
                    (
                        new RecursiveDirectoryIterator($directory),
                        RecursiveIteratorIterator::CHILD_FIRST
                    );

        # This will hold the result.
        $result = array();

        # Loop the directory contents.
        foreach ($iterator as $path) 
        {

            # If object is a directory and matches the search term ('models')...
            if ($path->isDir() && $path->getBasename() === $this->recursive['search']) 
            {

                # Add it to the result array.
                # Must replace the slash in the class - dunno why!
                $result[] = str_replace('\\', '/', $path).'/';
                //$result[] = (string) $path . '/';

            }

        }

        # Return the result in an array.
        return $result;
    }
}
like image 395
Run Avatar asked Mar 27 '13 20:03

Run


People also ask

How do you autoload in PHP?

The spl_autoload_register() function registers any number of autoloaders, enabling for classes and interfaces to be automatically loaded if they are currently not defined. By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error.

Can I implement multiple interfaces in PHP?

Classes may implement more than one interface if desired by separating each interface with a comma. A class can implement two interfaces which define a method with the same name, only if the method declaration in both interfaces is identical.

Can an abstract class implement an interface PHP?

PHP - Interfaces vs. All interface methods must be public, while abstract class methods is public or protected. All methods in an interface are abstract, so they cannot be implemented in code and the abstract keyword is not necessary. Classes can implement an interface while inheriting from another class at the same ...

What is the relation of Namespacing and autoloading PHP files?

Basically it says: "inside this directory, all namespaces are represented by sub directories and classes are <ClassName>. php files." Autoloading is PHP's way to automatically find classes and their corresponding files without having to require all of them manually.


1 Answers

PHP makes no difference between any class or interface or abstract class. The autoloader function you define always gets the name of the thing to autoload, and no kind of hint which one it was.

So your naming strategy cannot be autoloaded because you prefix interfaces with "interface_" and classes with "class_". Personally I find such a naming convention rather annoying.

On the other hand, your autoloader is completely unperformant. It scans whole directory trees recursively just to find one class! And the next class has to do all the work again, without the benefit of having done it before!

Please do implement a PSR-0 autoloader if you really want to do it on your own (and not use things like composer to do it for you) and stick to this naming scheme for classes and interfaces.

And please select a distinguishing classname prefix or namespace, and as a first step check inside your autoloader if the class to be loaded has this prefix. Return instantly if it has not. This frees you from having to spin the harddrive and see if the filename for the class exists.

If the prefix does not match, it is not "your" class that wants to be loaded, so your autoloader cannot know how to do it and shouldn't even try, but a different autoloader that was registered will know.

like image 154
Sven Avatar answered Nov 10 '22 08:11

Sven