¿Qué es la carga automática? ¿Cómo se usa spl_autoload, __autoload y spl_autoload_register?


204

Estoy aprendiendo estándares PHP avanzados e intentando implementar métodos nuevos y útiles. Anteriormente estaba usando __autoloadsolo para escapar, incluidos varios archivos en cada página, pero recientemente he visto un consejo sobre__autoload manual

spl_autoload_register () proporciona una alternativa más flexible para las clases de carga automática. Por esta razón, se desaconseja el uso de __autoload () y puede ser desaprobado o eliminado en el futuro.

pero realmente no puedo entender cómo implementar spl_autoloadyspl_autoload_register

Respuestas:


335

spl_autoload_register() le permite registrar múltiples funciones (o métodos estáticos de su propia clase Autoload) que PHP colocará en una pila / cola y llamará secuencialmente cuando se declare una "nueva Clase".

Así por ejemplo:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

En el ejemplo anterior, "MyClass" es el nombre de la clase que está intentando instanciar, PHP le pasa este nombre como una cadena spl_autoload_register(), lo que le permite elegir la variable y usarla para "incluir" la clase / archivo apropiado . Como resultado, no necesita incluir específicamente esa clase a través de una declaración de inclusión / requerimiento ...

Simplemente llame a la clase que desea instanciar como en el ejemplo anterior, y dado que registró una función (vía spl_autoload_register()) propia que determinará dónde están ubicadas todas sus clases, PHP usará esa función.

El beneficio de usar spl_autoload_register()es que, a diferencia de __autoload()usted, no necesita implementar una función de carga automática en cada archivo que cree. spl_autoload_register()también le permite registrar múltiples funciones de carga automática para acelerar la carga automática y hacerlo aún más fácil.

Ejemplo:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

Con respecto a spl_autoload , el manual dice:

Esta función está destinada a ser utilizada como una implementación predeterminada para __autoload(). Si no se especifica nada más y spl_autoload_register()se llama sin ningún parámetro, esta función se utilizará para cualquier llamada posterior __autoload().

En términos más prácticos, si todos sus archivos están ubicados en un solo directorio y su aplicación usa no solo archivos .php, sino también archivos de configuración personalizados con extensiones .inc, entonces una estrategia que podría usar sería agregar su directorio que contenga todos Los archivos a PHP incluyen ruta (vía set_include_path()).
Y dado que también necesita sus archivos de configuración, usaría spl_autoload_extensions()para enumerar las extensiones que desea que busque PHP.

Ejemplo:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Dado que spl_autoload es la implementación predeterminada del __autoload()método mágico, PHP llamará a spl_autoload cuando intentes crear una nueva clase.

Espero que esto ayude...


35
Esta puede ser una de las mejores respuestas en la historia de las respuestas. El respeto. Tuve uno de esos "¡Dios mío! ¡Todo tiene sentido ahora!" momentos gracias a ti, mi buen hombre. Creo que podría comenzar un club de fans.
Just Plain High

2
Para hacer de esta la mejor respuesta de todas las respuestas, incluso en universos alternativos, agregue que spl_autoload muy, um, "útilmente" (?) Convierte todos los nombres de archivo en minúsculas (vea mi comentario a @user a continuación). No puede usar spl_autoload_register () vainilla si le gustan sus CapitalLettersAndStuff.
Just Plain High

66
@Just Plain High No tengo ese problema y todos mis archivos de clase están en camello. Por cierto, esta es una respuesta maravillosa. ¡Me ayudó a entender un concepto simple que no podía entender hasta que leí esta publicación! ¡Mi archivo de 85 líneas (y en crecimiento) que incluye todos mis archivos de clase ahora tiene 7 líneas!
kyle

2
De hecho, esta es una buena respuesta, pero me falta una cosa. ¿Cuál es la funcionalidad predeterminada real? Con las clases que conozco, usa el espacio de nombres como ruta y el nombre de clase como nombre de archivo. Aunque no puedo entender cómo funciona con las funciones.
SiXoS

2
¿No es uno de los grandes beneficios de usar spl_autoload_register()(y __autoload()en general) que las cargas perezosas incluyen archivos / clases? Esto está implícito en la respuesta, pero no se establece explícitamente. ¡Para mí, esta es información crítica que sería perfecta para incluir en su respuesta! :)
rinogo

13

Desde PHP 5.3, puede usar spl_autoload_register()espacios de nombres, lo que significa que puede organizar su proyecto y cargar automáticamente sus clases de php sin requerir o incluir y sin redefinir una __autoload()función.

Para demostrar este comportamiento, simplemente cree un archivo llamado index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Luego, cree una carpeta llamada Main ubicada justo al lado del archivo index.php. Finalmente, crea un archivo llamado Application.php ubicado en Main y pega el siguiente código en él:

<?php namespace Main;
class Application{}

9
Una nota de mi jugueteo con todo esto: spl_autoload () - y por lo tanto spl_autoload_register () - convierte los nombres de archivo a minúsculas (a pesar de informes de errores, súplicas y votaciones furiosas). Esto significa que puede estar buscando "Main \ Application" pero spl_autoload está buscando "main \ application". Si te gustan los camellos, como a mí, tendrás que escribir tu propia función. Aquí hay un buen ejemplo de inicio: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High el

1
Pros: spl_autoload_register () es el método más rápido de carga automática Contras: solo funcionará con archivos / clases en minúsculas, y espacios de nombres también, que en este día y edad simplemente suman mucho tiempo (no hay opción para decirle que use CamelCase, etc.). Pero si puedes vivir con la estructura de espacio de nombres / classname.php, no busques más.
stamster

1
spl_autoload_register()la implementación predeterminada no puede encontrar clases heredadas. Entonces, usando valores predeterminados, archivos en minúsculas y directorios que reflejan la ruta del espacio de nombres, todo funciona bien a menos que tenga una clase que extienda otra clase (padre). PHP luego arroja un error de que no puede encontrar esa clase padre, ¡incluso si todos están en el mismo directorio / espacio de nombres! Lo que es confuso es que, literalmente, solo se encuentran las clases de primer nivel, por lo que tuve que poner otra spl_autoload_register()con una regla de función anónima justo después de la primera para poder incluir manualmente las clases principales / heredadas que faltan.
stamster

1

Aquí está la forma en que uso Autoload. En el ejemplo dado, quiero cargar clases de 3 directorios diferentes.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

En el ejemplo dado, el PHP buscará el espacio de nombres \ clase en estos tres directorios usando estos tres formatos de nombre de archivo diferentes.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.