Cargando archivos y clases dinámicamente

La clase Zend_Loader incluye métodos para ayudar a cargar archivos dinámicamente.

Zend_Loader vs. require_once()

Los métodos de Zend_Loader tienen más utilidad si el nombre de archivo que necesita cargar es variable. Por ejemplo, si éste se basa en un parametro de entrada del usuario o argumento de un método. Si carga un archivo o clase cuyo nombre es constante, no hay ningún beneficio al usar Zend_Loader sobre el uso de funciones tradicionales de PHP como require_once() .

Cargando Archivos

El método estático Zend_Loader::loadFile() carga un archivo PHP . El archivo cargado puede contener cualquier código PHP . El método se comporta como un envoltorio para la función PHP include() . Este método devuelve un booleano FALSE en caso de fallo, por ejemplo, si el archivo especificado no existe.

Ejemplo 505. Ejemplo del Método loadFile()

Zend_Loader::loadFile($filename, $dirs=null, $once=false);

El argumento $filename especifica el archivo que se va a cargar, el cual no debe contener ninguna información de rutas. Una verificación de seguridad es efectuada sobre $filename . El archivo $filename sólo puede contener caracteres alfanuméricos, guiones ("-"), barras bajas ("_"), o puntos ("."). No hay ninguna restricción en el argumento $dirs .

El parámetro $dirs especifica en qué carpetas buscar el archivo. Si el valor es NULL , sólo se buscará en el include_path ; si el valor es un string o un array, se buscará en la carpeta o carpetas especificadas , seguidas del include_path .

El argumento $once es un booleano. Si es TRUE , Zend_Loader::loadFile() esa la función PHP include_once() para cargar el archivo, de lo contrario se utiliza la función PHP include() .

Cargando Clases

El método estático Zend_Loader::loadClass($class, $dirs) carga un archivo PHP y comprueba la existencia de la clase.

Ejemplo 506. Ejemplo del método loadClass()

Zend_Loader::loadClass('Container_Tree',
    array(
        '/home/production/mylib',
        '/home/production/myapp'
    )
);

La cadena que especifica la clase es convertida a una ruta relativa sustituyendo las barras bajas (_) por el separador de carpeta de su Sistema Operativo, y añadiendo '.php'. En el ejemplo de arriba, 'Container_Tree' se convierte en 'Container\\Tree.php' en Windows.

Si $dirs es una cadena o un array, Zend_Loader::loadClass() busca las carpetas en el orden suministrado. El primer archivo encontrado es cargado. Si el archivo no existe en el $dirs especificado, entonces se busca en el include_path del entorno PHP .

Si el archivo no es encontrado o la clase no existe después de la carga, Zend_Loader::loadClass() lanza una Zend_Exception .

Zend_Loader::loadFile() se usa para cargar, así que el nombre de la clase puede contener únicamente caracteres alfanuméricos, guiones ('-'), barras bajas ('_'), y puntos ('.').

Loading Classes from PHP Namespaces

Starting in version 1.10.0, Zend Framework now allows loading classes from PHP namespaces. This support follows the same guidelines and implementation as that found in the PHP Framework Interop Group PSR-0 reference implementation.

Under this guideline, the following rules apply:

  • Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.

  • Each "_" character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR. The "_" character has no special meaning in the namespace.

  • The fully-qualified namespace and class is suffixed with ".php" when loading from the file system.

As examples:

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php

  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

Comprobando si un Archivo Puede Ser Leído

El método estático Zend_Loader::isReadable($pathname) devuelve TRUE si el archivo en la ruta $pathname existe y tiene permisos de lectura, FALSE en caso contrario.

Ejemplo 507. Ejemplo del método isReadable()

if (Zend_Loader::isReadable($filename)) {
    // hace algo con $filename
}

El argumento $filename especifica el nombre de archivo que comprobar. Puede contener información de la ruta. Este método envuelve la función PHP is_readable() . La función PHP no busca en include_path , mientras que Zend_Loader::isReadable() sí.

Usando el Autoloader

La clase Zend_Loader contiene un método que se puede registrar con PHP SPL autoloader. Zend_Loader::autoload() es el método callback. Por comodidad, Zend_Loader permite a la función registerAutoload() registrar su método autoload() . Si la extensión spl_autoload no está presente en el entorno PHP , entonces el método registerAutoload() lanza una Zend_Exception .

Ejemplo 508. Ejemplo de registro del método callback del autoloader

Zend_Loader::registerAutoload();

Después de registrar el callback de autoload de Zend Framework, se pueden referenciar clases de Zend Framework sin tener que cargarlas explícitamente. El método autoload() usa automáticamente Zend_Loader::loadClass() cuando referencie una clase.

Si ha extendido la clase Zend_Loader , se puede pasar un argumento opcional a registerAutoload() , para especificar la clase a partir de la cual registrar un método autoload() .

Ejemplo 509. Ejemplo de registro del método de callback autoload desde una clase extendida

Debido a la semántica de referencia de funciones estáticas en PHP , se debe implementar código tanto para la clase loadClass() como autoload() , y autoload() debe llamar a self::loadClass() . Si su método autoload() delega en su padre la llamada a self::loadClass() , entonces llamará al método con ese nombre en la clase padre, no la subclase.

class My_Loader extends Zend_Loader
{
    public static function loadClass($class, $dirs = null)
    {
        parent::loadClass($class, $dirs);
    }

    public static function autoload($class)
    {
        try {
            self::loadClass($class);
            return $class;
        } catch (Exception $e) {
            return false;
        }
    }
}

Zend_Loader::registerAutoload('My_Loader');

Se puede eliminar un callback de autoload. registerAutoload() tiene un segundo parámetro opcional, que es TRUE por defecto. Si este parámetro es FALSE , el callback de autoload será borrado de la pila de autoload SPL.