What is spl_autoloader_register in PHP?

Asked

Viewed 2,472 times

14

What is the role of the spl_autoloader_register, and in which possible scenarios this function could be included?

1 answer

12


The spl_autoloader_register is a function that is part of the SPL which means Standard PHP Library, which in English would be something like Standard PHP library

Maybe a better adapted translation would be:

  • PHP library for standards
  • PHP library for common situations
  • PHP library for common problems

It has been developed to help solve a number of common problems and is available since PHP5.0

List of interfaces and functions

  • class_implements - Returns interfaces that are implemented by the class
  • class_parents - Returns the parent classes of a given class
  • class_uses - Returns the traits used by a particular class
  • iterator_apply - Calls a function all element in an "iterator"
  • iterator_count - Counts the number of elements in the "iterator"
  • iterator_to_array - Copies the iterator in an array
  • spl_autoload_call - Tries all functions __autoload() registered to load the requested class
  • spl_autoload_extensions - Logs and returns standard file extensions for spl_autoload
  • spl_autoload_functions - Returns all functions __autoload() registered
  • spl_autoload_register - Records the given function as an implementation of __autoload()
  • spl_autoload_unregister - Removes the function given as implementation of __autoload()
  • spl_autoload - Standard implementation of __autoload()
  • spl_classes - Returns available SPL classes
  • spl_object_hash - Returns a hash identification of the given object

In the specific case of spl_autoload_register It is often used to record events called. A good example of use would be to load a class from another file only when needed.

For example, let’s imagine that we have a file called global.php:

<?php
function meuAutoload($pClassName) {
    $path = __DIR__ . '/libs/' . strtolower($pClassName) . '.php';
    if (is_file($path)) {
        include_once $path;
    }
}
spl_autoload_register('meuAutoload');

You can use in index.php something like:

<?php
require 'global.php';

$foo = new Foo();
$foo->test();

Note that I did not declare the class Foo, then the function meuAutoload will attempt to load the file into the folder /libs/foo.php, if the file does not exist, then it will issue an error.

To avoid the error simply add in the libs folder the foo.php file, with the contents:

<?php
class Foo
{
    public function test()
    {
       //Algo aqui
    }
}

Perks:

  • You just call libraries that you’ll actually use
  • It is called only if the class nay is defined
  • Improves the performance of the script, since only what you will use will be added
  • No need to include "manually" with require or include the classes/libraries required.

PSR-0 and PSR-4

The spl_autoloader_register is used by PSR-0 http://www.php-fig.org/psr/psr-0/pt-br/ and the PSR-4 which are standards for automatic library loading.

Note that the PSR-0 is out of use and should use the PSR-4.

I will mention only on PSR-4, due to the PSR-0 being in disuse, the main difference of the PSR-4 pro example I showed earlier is that it works with namespaces and a folder structure to organize your library, this is widely used by several current frameworks, as for example the Laravel.

See an example code, create a file called global.php:

function myAutoLoader($class)
{
    // Prefixo no namespace do projeto especifico 
    $prefix = 'Foo\\Bar\\';

    // Diretorio aonde ficam as bibliotecas
    $base_dir = __DIR__ . '/src/';

    // Verifica se a classe chamada usa o prefixo
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // Se não usar o prefixo Foo\bar então retorna false
        return;
    }

    // Pega o caminho relativo da classe, ou seja remove o Foo\bar\
    $relative_class = substr($class, $len);

    // Troca os separadores de namespace por separadores de diretorio
    // e adiciona o .php
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

    // Verifica se o arquivo existe, se existir então inclui ele 
    if (is_file($file)) {
        include_once $file;
    }
}

spl_autoload_register('myAutoLoader');

My code has some details different from the original, but they are pertinent things in my view to avoid failures, as for example, I exchanged file_exists for is_file and I also didn’t use an anonymous function to support php5.3, I also switched require for include_once to prevent the require emits some more error (as described here Autoload PSR4 class)

A very important detail, the function used in the PSR-4 should not issue errors, or interfere with the exception, the purpose is only to include the library, in case the file does not exist the error should be the default that is generated by php itself, something like:

Fatal error: Class 'Foo Bar olamundo' not found in /home/user/project/index.php on line 2

To use, do this:

<?php
require 'global.php';

/*
Isto irá incluir ./src/exemplo1.php
*/
use Foo\Bar\exemplo1 as ApelidoParaExemplo1;
$foo = new ApelidoParaExemplo1;

/*
Isto irá incluir ./src/exemplo2.php
*/
$foo = new Foo\Bar\exemplo2;
$foo->teste();

/*
Isto irá incluir ./src/exemplo3.php
*/
class Teste extends Foo\Bar\exemplo3 {
}

/*
Isto irá causar erro, porque não usou o namespace padrão
*/
$foo = new Hello\Bar\exemplo2;

/*
Isto irá incluir ./src/a/b/c/d/teste.php
*/
$foo = new Foo\Bar\a\b\c\d\teste;

Note that all included files must be within namespaces called, read about namespaces here http://php.net/manual/en/language.namespaces.php.

The files used in the example should be something like:

Filing cabinet ./src/exemplo1.php:

namespace Foo\Bar;

class exemplo1
{
   //Algo aqui
}

Filing cabinet ./src/exemplo2.php:

namespace Foo\Bar;

class exemplo2
{
   //Algo aqui
}

Filing cabinet ./src/exemplo3.php:

namespace Foo\Bar;

class exemplo3
{
   //Algo aqui
}

Filing cabinet ./src/a/b/c/d/teste.php:

namespace Foo\Bar\a\b\c\d;

class teste
{
   //Algo aqui
}

Note that if you use something like:

use Foo\Bar\Baz;

And not execute new Baz or a static method or variable for example Baz::foo(); autoload will not include the file as it is not necessary, the use is just to create the nickname or shortcut, because using use that instead of using Foo\Bar\Baz you can use only Baz

Related questions:

  • 2

    wow, I guess I couldn’t have hoped better, really good..

Browser other questions tagged

You are not signed in. Login or sign up in order to post.