Loader

The Phalcon\Autoload\Loader
class has been renamed Phalcon\Autoload\Loader
. La funcionalidad sigue siendo la misma.
Resumen
Phalcon\Autoload\Loader is an autoloader that implements PSR-4. Como cualquier autocargador, dependiendo de su configuración, intentará encontrar los ficheros que su código está buscando en base a fichero, clase, espacio de nombres, etc. Como este componente está escrito en C, ofrece la menor sobrecarga al procesar su configuración, ofreciendo así un aumento de rendimiento.

This component relies on PHP’s autoloading classes capability. Si una clase definida en el código todavía no se ha incluido, un manejador especial intentará cargarla. Phalcon\Autoload\Loader serves as the special handler for this operation. Al cargar clases en función de la necesidad de carga, el rendimiento general aumenta, ya que las únicas lecturas de archivos se producen para los ficheros necesarios. This technique is called lazy initialization.
El componente ofrece opciones para cargar ficheros basados en su clase, nombre de fichero, directorios en su sistema de ficheros así como extensiones de fichero.
Registro
Usually we would use the spl_autoload_register() to register a custom autoloader for our application. Phalcon\Autoload\Loader hides this complexity. Después defina todos sus espacios de nombres, clases, directorios y ficheros que necesitará llamar a la función register()
, y el autocargador está listo para usar.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Models' => 'app/models',
]
);
$loader->register();
register()
uses spl_autoload_register() internally. Como resultado, acepta también el parámetro booleano prepend
. Si es suministrado y es true
, el autocargador se añadirá al inicio de la cola de autocarga en lugar de al final (comportamiento predeterminado).
Siempre puede llamar al método isRegistered()
para comprobar si su autocargador está registrado o no.
NOTE: If there is an error in registering the autoloader, the component will throw an exception.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Models' => 'app/models',
]
);
$loader->register();
echo $loader->isRegistered(); // true
Desregistrar el autocargador es igualmente fácil. Todo lo que necesita es llamar a unregister()
.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Models' => 'app/models',
]
);
$loader->register();
if (true === $loader->isRegistered()) {
$loader->unregister();
}
Capa de seguridad
Phalcon\Autoload\Loader incorporates a security layer, by sanitizing class names by default i.e. removing invalid characters. Esto dificulta que se inyecte código malicioso en su aplicación.
Considere el ejemplo siguiente:
<?php
spl_autoload_register(
function (string $className) {
$filepath = $className . '.php';
if (file_exists($filepath)) {
require $filepath;
}
}
);
The above autoloader lacks any kind of security. If a part of your code accidentally calls the autoloader with a name that points to a script containing malicious code, then your application will be compromised.
<?php
$className = '../processes/important-process';
if (class_exists($className)) {
// ...
}
En el fragmento anterior, si ../processes/important-process.php
es un fichero válido, podría haber sido subido por un hacker o desde un proceso de subida no tan cuidadoso, entonces un usuario externo podría ejecutar el código sin ninguna autorización y posteriormente obtener acceso a toda la aplicación si no al servidor.
To avoid most of these kind of attacks, Phalcon\Autoload\Loader removes invalid characters from the class name.
Espacios de nombres
Una forma muy popular de organizar su aplicación es con directorios, cada uno representando un espacio de nombres en particular. Phalcon\Autoload\Loader can register those namespace to directory mapping and traverse those directories to search the file that your application is requiring.
The setNamespaces()
method accepts an array, where keys are the namespaces and values are the actual directories in the file system. El separador de espacio de nombres se sustituirá por el separador de directorio cuando el cargador intente encontrar las clases.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Controllers' => 'app/controllers',
'MyApp\Models' => 'app/models',
]
);
$loader->register();
En el ejemplo anterior, cuando hacemos referencia a un controlador, el cargador lo buscará en app/controllers
y sus subdirectorios. Similarly, for a model the search will occur in app/models
.
You do not need to register the sub namespaces, if the actual files are located in subdirectories that map the namespace naming convention.
Así por ejemplo, el ejemplo anterior define nuestro espacio de nombres MyApp
para apuntar a app/library
. Si tenemos un fichero:
/app/library/Components/Mail.php
que tiene un espacio de nombres de:
then the loader, as defined above, does not need to know about the MyApp\Components
namespace location, or have it defined in the `
()` declaration.
If the component referenced in the code is MyApp\Components\Mail
, it will assume that it is a subdirectory of the root namespace. Sin embargo, ya que especificamos una ubicación diferente para los espacios de nombres MyApp\Controllers
y MyApp\Models
, el cargador buscará esos espacios de nombres en los directorios especificados.
The setNamespaces()
method also accepts a second parameter merge
. By default, it is false
. You can however set it to true
when having multiple calls to setNamespaces()
so that the namespace definitions are merged.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
]
);
$loader->setNamespaces(
[
'MyApp\Controllers' => 'app/controllers',
'MyApp\Models' => 'app/models',
],
true
);
$loader->register();
The above example merges the second declaration of setNamespaces()
with the previous one.
Si necesita comprobar qué espacios de nombres están registrados en el autocargador, puede usar el getter getNamespaces()
, que devuelve el vector de los espacios de nombres registrados. Para el ejemplo anterior, getNamespaces()
devuelve:
[
'MyApp' => 'app/library',
'MyApp\Controllers' => 'app/controllers',
'MyApp\Models' => 'app/models',
]
Clases
Another way to let Phalcon\Autoload\Loader know where your components/classes are located, so that the autoloader can load them properly, is by using setClasses()
.
El método acepta un vector, donde la clave es la clase con el espacio de nombres y el valor es la ubicación del fichero que contiene la clase. Como era de esperar, esta es la manera más rápida de autocargar una clase, ya que el autocargador no necesita escanear o sacar estadísticas de ficheros para encontrar las referencias de los ficheros.
Sin embargo, usar este método puede dificultar el mantenimiento de su aplicación. The more your application grows, the more files are added, the easier it becomes to make a mistake while maintaining the list of files used in setClasses()
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setClasses(
[
'MyApp\Components\Mail' => 'app/library/Components/Mail.php',
'MyApp\Controllers\IndexController' => 'app/controllers/IndexController.php',
'MyApp\Controllers\AdminController' => 'app/controllers/AdminController.php',
'MyApp\Models\Invoices' => 'app/models/Invoices.php',
'MyApp\Models\Users' => 'app/models/Users.php',
]
);
$loader->register();
En el ejemplo anterior, estamos definiendo la relación entre una clase con espacio de nombres y un fichero. Como puede ver, el cargador será tan rápido como pueda pero la lista empezará a crecer, cuanto más crece nuestra aplicación, dificultando el mantenimiento. Sin embargo, si su aplicación no tiene demasiados componentes, no hay razón por la que no pueda usar este método de autocarga de componentes.
The setClasses()
method also accepts a second parameter merge
. By default, it is false
. You can however set it to true
when having multiple calls to setClasses()
so that the class definitions are merged.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setClasses(
[
'MyApp\Components\Mail' => 'app/library/Components/Mail.php',
'MyApp\Controllers\IndexController' => 'app/controllers/IndexController.php',
'MyApp\Controllers\AdminController' => 'app/controllers/AdminController.php',
]
);
$loader->setClasses(
[
'MyApp\Models\Invoices' => 'app/models/Invoices.php',
'MyApp\Models\Users' => 'app/models/Users.php',
],
true
);
$loader->register();
The above example merges the second declaration of setClasses()
with the previous one.
Si necesita comprobar qué clases están registradas en el autocargador, puede usar el getter getClasses()
, que devuelve el vector de las clases registradas. Para el ejemplo anterior, getClasses()
devuelve:
[
'MyApp\Components\Mail' => 'app/library/Components/Mail.php',
'MyApp\Controllers\IndexController' => 'app/controllers/IndexController.php',
'MyApp\Controllers\AdminController' => 'app/controllers/AdminController.php',
'MyApp\Models\Invoices' => 'app/models/Invoices.php',
'MyApp\Models\Users' => 'app/models/Users.php',
]
Archivos
There are times that you might need to require a specific file that contains a class without a namespace or a file that contains some code that you need. Un ejemplo sería un fichero que contiene funciones de depuración prácticas.
Phalcon\Autoload\Loader offers setFiles()
which is used to require such files. Acepta un vector, que contiene el nombre y localización de cada fichero.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setFiles(
[
'functions.php',
'arrayFunctions.php',
]
);
$loader->register();
Estos ficheros se cargan automáticamente cuando se llama al método register()
.
The setFiles()
method also accepts a second parameter merge
. By default, it is false
. You can however set it to true
when having multiple calls to setFiles()
so that the file definitions are merged.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setFiles(
[
'app/functions/functions.php',
]
);
$loader->setFiles(
[
'app/functions/debug.php',
],
true
);
$loader->register();
The above example merges the second declaration of setFiles()
with the previous one.
Si necesita comprobar qué ficheros están registrados en el autocargador, puede usar el getter getFiles()
, que devuelve el vector de los ficheros registrados. Para el ejemplo anterior, getFiles()
devuelve:
[
'app/functions/functions.php',
'app/functions/debug.php',
]
También tiene acceso al método loadFiles()
, que recorrerá todos los ficheros registrados y si existen los requerirá
. Este método se llama automáticamente cuando se llama a register()
.
Directorios
Another way to let Phalcon\Autoload\Loader know where your application files are is to register directories. Cuando un fichero necesita ser requerido por la aplicación, el autocargador escaneará los directorios registrados para encontrar el fichero referenciado para poder requerirlo.
The setDirectories()
method accepts an array with each element being a directory in the file system containing the files that will be required by the application.
Este tipo de registro no se recomienda en términos de rendimiento. Additionally, the order of declared directories matters, since the autoloader tries to locate the files by searching directories sequentially. Como resultado, el directorio que contiene los ficheros más referenciados debería declararse primero, etc.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setDirectories(
[
'app/functions',
'app/controllers',
'app/models',
]
);
$loader->register();
The setDirectories()
method also accepts a second parameter merge
. By default, it is false
. You can however set it to true
when having multiple calls to setDirectories()
so that the class definitions are merged.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setDirectories(
[
'app/functions',
]
);
$loader->setDirectories(
[
'app/controllers',
'app/models',
],
true
);
$loader->register();
The above example merges the second declaration of setDirectories()
with the previous one.
Si necesita comprobar qué directorios están registrados en el autocargador, puede usar el getter getDirs()
, que devuelve el vector de los directorios registrados. Para el ejemplo anterior, getDirs()
devuelve:
[
'app/functions',
'app/controllers',
'app/models',
]
Extensiones de Ficheros
When you use the setNamespaces()
and setDirectories()
, Phalcon\Autoload\Loader automatically assumes that your files will have the .php
extension. Puede cambiar este comportamiento usando el método setExtensions()
. El método acepta un vector, donde cada elemento es la extensión a comprobar (sin el .
):
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setExtensions(
[
'php',
'inc',
'phb',
]
);
$loader->setDirectories(
[
'app/functions',
]
);
En el ejemplo anterior, cuando se referencia un fichero Mail
, el autocargador buscará en app/functions
los siguientes archivos:
Mail.php
Mail.inc
Mail.phb
Los ficheros se comprueban en el orden en el que se define cada extensión.
Función de Retorno de Comprobación de Fichero
Puede acelerar el cargador configurando un método distinto de llamada de retorno de comprobación de fichero usando el método setFileCheckingCallback()
.
The default behavior uses is_file. However, you can also use null
which will not check whether a file exists or not, before loading it, or you can use stream_resolve_include_path which is much faster than is_file but will cause problems if the target file is removed from the file system.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setFileCheckingCallback("is_file");
Comportamiento predeterminado
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setFileCheckingCallback("stream_resolve_include_path");
Más rápido que is_file()
, pero introduce problemas si el fichero se elimina del sistema de ficheros.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader();
$loader->setFileCheckingCallback(null);
No comprueba la existencia del fichero.
Eventos
El componente [Gestor de Eventos][events] ofrece ganchos que se pueden implementar para observar o expandir la funcionalidad del cargador. The Phalcon\Autoload\Loader implements the Phalcon\Events\EventsAwareInterface, and therefore the getEventsManager()
and setEventsManager()
methods are available.
Los siguientes eventos están disponibles:
Evento |
Descripción |
¿Detiene la operación? |
afterCheckClass |
Se dispara al final del proceso de autocarga cuando la clase no ha sido encontrada. |
No |
beforeCheckClass |
Se dispara al principio del proceso de autocarga, antes de comprobar la clase. |
Si |
beforeCheckPath |
Se dispara antes de comprobar un directorio por un fichero de clase. |
Si |
pathFound |
Se dispara cuando el cargador localiza un fichero de clase o un fichero en un directorio registrado |
Si |
El el siguiente ejemplo, el Gestor de Eventos
trabaja con la clase cargador, ofreciendo información adicional en el flujo de operación:
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager;
use Phalcon\Autoload\Loader;
$eventsManager = new Manager();
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Models' => 'app/models',
]
);
$eventsManager->attach(
'loader:beforeCheckPath',
function (
Event $event,
Loader $loader
) {
echo $loader->getCheckedPath();
}
);
$loader->setEventsManager($eventsManager);
$loader->register();
En el ejemplo anterior, creamos un nuevo objeto Gestor de Eventos, adjuntamos un método al evento loader:beforeCheckPath
y lo registramos en nuestro autocargador. Cada vez que el cargador itere y busque un fichero particular en una ruta específica, la ruta será mostrada por pantalla.
getCheckedPath()
mantiene la ruta que se escanea durante cada iteración del bucle interno. Also, you can use the getfoundPath()
method, which holds the path of the found file during the internal loop.
Para eventos que pueden parar la operación, todo lo que necesitará hacer es devolver false
en el método adjunto al evento en particular:
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager;
use Phalcon\Autoload\Loader;
$eventsManager = new Manager();
$loader = new Loader();
$loader->setNamespaces(
[
'MyApp' => 'app/library',
'MyApp\Models' => 'app/models',
]
);
$eventsManager->attach(
'loader:beforeCheckPath',
function (
Event $event,
Loader $loader
) {
if ('app/models' === $loader->getCheckedPath()) {
return false;
}
}
);
$loader->setEventsManager($eventsManager);
$loader->register();
En el ejemplo anterior, cuando el autocargador empieza a escanear la carpeta app/models
por el espacio de nombres MyApp\Models
, detendrá la operación.
Resolución de problemas
Algunas cosas a tener en cuenta cuando se usa el autocargador:
- The autoloading process is case-sensitive
- Las estrategias basadas en espacios de nombres/prefijos son más rápidas que la estrategia de directorios
- If a bytecode cache, such as APCu, is installed, it will be used to get the requested file (an implicit caching of the file is performed)
Debugging
The Phalcon\Autoload\Loader
can be instantiated with passing true
to the constructor, so that you can enable debug mode. In debug mode, the loader will collect data about searching and finding files that are requested. You can then use the getDebug()
method to output the debug messages, to diagnose issues.
<?php
use Phalcon\Autoload\Loader;
$loader = new Loader(true);
$directory = dataDir('some/directory/');
$loader->addDirectory($directory);
$loader->autoload('Simple');
var_dump($loader->getDebug());
// [
// 'Loading: Simple',
// 'Class: 404: Simple',
// 'Namespace: 404: Simple',
// 'Require: some/directory/Simple.php',
// 'Directories: some/directory/Simple.php',
// ];
Métodos
public function __construct(bool $isDebug = false)
Constructor. If $isDebug
is true
, debugging information will be collected.
public function addClass(string $name, string $file): Loader
Adds a class to the internal collection for the mapping
public function addDirectory(string $directory): Loader
Adds a directory for the loaded files
public function addExtension(string $extension): Loader
Adds an extension for the loaded files
public function addFile(string $file): Loader
Adds a file to be added to the loader
public function addNamespace(
string $name,
mixed $directories,
bool $prepend = false
): Loade
Adds a namespace to the loader, mapping it to different directories. The third parameter allows to prepend the namespace.
public function autoload(string $className): bool
Carga automáticamente las clases registradas
public function getCheckedPath(): string | null
Obtiene la ruta que está revisando el cargador para un ruta específica
public function getClasses(): array
Devuelve el mapa de clases que actualmente tiene registrado el auto cargador
public function getDebug(): array
Returns debug information collected
public function getDirectories(): array
Devuelve los directorios registrados actualmente en el autocargador
public function getExtensions(): array
Devuelve las extensiones de archivo registradas en el cargador
public function getFiles(): array
Devuelve los archivos registrados actualmente en el auto cargador
public function getFoundPath(): string | null
Obtiene la ruta cuando una clase fue encontrada
public function getNamespaces(): array
Devuelve los espacios de nombres registrados actualmente en el autocargador
public function loadFiles(): void
Comprueba si un archivo existe y a continuación añade el archivo haciendo un require
virtual
public function register(bool $prepend = false): Loader
Registrar el método de autocarga
public function setClasses(
array $classes,
bool $merge = false
): Loader
Registra las clases y sus ubicaciones
public function setDirectories(
array $directories,
bool $merge = false
): Loader
Registra los directorios en los que se pueden localizar las clases “no encontradas”
public function setExtensions(
array $extensions,
bool $merge = false
): Loader
Sets an array of file extensions that the loader must try in each attempt to locate the file
public function setFileCheckingCallback(
mixed $method = null
): Loader
Establece la función de retorno de la comprobación de fichero.
public function setFiles(
array $files,
bool $merge = false
): Loader
Register files that are “non-classes” hence need a “require”. This is very useful for including files that only have functions
public function setNamespaces(
array namespaces,
bool merge = false
): Loader
Registra los espacios de nombres y sus directorios relacionados
public function unregister(): Loader
Anula el registro del método de autocarga