Auto Load classes in PHP

2

I'm developing a mini framework to use in my applications and auto-load classes like this:

function __autoload($Class) {

    $cDir = ['Conn', 'Helpers', 'Models'];
    $iDir = null;

    foreach ($cDir as $dirName):
        if (!$iDir && file_exists(__DIR__ . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $Class . '.class.php') && !is_dir(__DIR__ . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $Class . '.class.php')):
            include_once (__DIR__ . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . $Class . '.class.php');
            $iDir = true;
        endif;
    endforeach;

    if (!$iDir):
        trigger_error("Não foi possível incluir {$Class}.class.php", E_USER_ERROR);
        die;
    endif;

}

How can I optimize this code?

    
asked by anonymous 04.09.2016 / 16:34

3 answers

4

You can do the following by first improving the readability of the code, using simpler names to make it easier to understand and using the normal syntax of if and foreach .

Then by using the spl_autoload_register function to the magic method variables __autoload , because using the spl_autoload_register function, you have the possibility to register more than one autoload function for your classes.

Also remember that the magic method __autoload , may no longer exist in future versions of PHP, as this function is obsolete according to its documentation.

<?php

// AUTO LOAD DE CLASSES ####################
function myAutoload($className) {

    $directoryNames = ['Conn', 'Helpers', 'Models'];
    $includedClass = false;

    foreach ($directoryNames as $directoryName) {

        $path = __DIR__ . DIRECTORY_SEPARATOR . $directoryName . DIRECTORY_SEPARATOR . $className . '.class.php';

        if (!$directoryName && file_exists($path) && !is_dir($path)) {

            include_once ($path);
            $includedClass = true;

        };

    }

    if (!$includedClass) {
        trigger_error("Não foi possível incluir {$className}.class.php", E_USER_ERROR);
        die;
    }

}

//Usando essa função você pode usar mais de uma função para autoload.
spl_autoload_register("myAutoload");

Also, while creating your own autoload function, you could use a ready-made specification that is PSR-4 for classloads in PHP.

    
04.09.2016 / 17:15
3

You can optimize by eliminating the technique that iterates through an array of directories.

$cDir = array('pasta1', 'pasta2', 'pasta3')
foreach ($cDir as $dirName) {
    // aqui vai repetir, buscando nos diretórios registrados até encontrar.
    // isso é redundante e pode ser evitado
}

One suggestion is to standardize on recommendations from php-fig.org .
You must have seen something like PHP PSR, PSR4, etc. somewhere. The PSR stands for > PHP Standards Recommendation.
It is not a rule that everyone should follow. It is optional.

Optimizing with PSR4

To optimize your autoload, you could do something in the PSR4 pattern:

spl_autoload_register(function ($class) {

    // project-specific namespace prefix
    $prefix = 'Foo\Bar\';

    // base directory for the namespace prefix
    $base_dir = __DIR__ . '/src/';

    // does the class use the namespace prefix?
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return;
    }

    // get the relative class name
    $relative_class = substr($class, $len);

    // replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace('\', '/', $relative_class) . '.php';

    // if the file exists, require it
    if (file_exists($file)) {
        require $file;
    }
});
It's just that. The only thing you would change is the prefix of your namespace and the basis of the files.

$prefix = 'Foo\Bar\';

If your namespace is Qualquer\Outro\Nome , it would look like this

$prefix = 'Qualquer\Outro\Nome\';

The base of the files is defined in this section

$base_dir = __DIR__ . '/src/';

Just set up the base according to your project.

Obviously you will have to use namespace in your files that you want to load.

The naming of directories and files should follow the same pattern as the class name.

Example, when instantiating a class:

new \Foo\Bar\Baz\Qux;

The autoload of the above example will recognize the excerpt of the namespace prefix: \Foo\Bar and com will work with the rest Baz\Qux

Forming this way, the location of the file is

/www/site/src/Baz/Qux.php

This logic eliminates all the cost of iterating an array to go through directories that are most often unnecessary and still run the risk of colliding with an equal name into different directories.

This array technique was useful for a time when PHP still did not have the namespaces feature. a>, available from PHP5.3.

Related to the namespace: How do namespaces work in PHP?

    
04.09.2016 / 20:50
-1
                $pastas = ['dir1', 'dir2', 'dir3'];
                foreach($diretorios as $pacth)
                {
                    foreach(glob("asset/$pacth/*.class.php") as $filename){
                    require_once $filename;
                }
            }
    
04.09.2016 / 21:01