<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.loader.load">
    <title>Loading Files and Classes Dynamically</title>

    <para>
        The <classname>Zend_Loader</classname> class includes methods to help you load files
        dynamically.
    </para>

    <tip>
        <title>Zend_Loader vs. require_once()</title>

        <para>
            The <classname>Zend_Loader</classname> methods are best used if the filename you need to
            load is variable. For example, if it is based on a parameter from
            user input or method argument. If you are loading a file or a
            class whose name is constant, there is no benefit to using
            <classname>Zend_Loader</classname> over using traditional <acronym>PHP</acronym>
            functions such as <ulink
                url="http://php.net/require_once"><methodname>require_once()</methodname></ulink>.
        </para>
    </tip>

    <sect2 id="zend.loader.load.file">
        <title>Loading Files</title>

        <para>
            The static method <methodname>Zend_Loader::loadFile()</methodname> loads a
            <acronym>PHP</acronym> file. The file loaded may contain any <acronym>PHP</acronym>
            code. The method is a wrapper for the <acronym>PHP</acronym> function
            <ulink url="http://php.net/include"><methodname>include()</methodname></ulink>,
            which emits a <acronym>PHP</acronym> warning on failure, for example
            if the specified file does not exist.
        </para>

        <example id="zend.loader.load.file.example">
            <title>Example of the loadFile() Method</title>

            <programlisting language="php"><![CDATA[
Zend_Loader::loadFile($filename, $dirs=null, $once=false);
]]></programlisting>
    </example>

        <para>
            The <varname>$filename</varname> argument specifies the filename to load,
            which must not contain any path information.
            A security check is performed on <varname>$filename</varname>.
            The <varname>$filename</varname> may only contain alphanumeric characters,
            dashes ("-"), underscores ("_"), or periods (".").
            No such restriction is placed on the <varname>$dirs</varname> argument.
        </para>

        <para>
            The <varname>$dirs</varname> argument specifies which directories to search for the
            file in. If the value is <constant>NULL</constant>, only the include_path
            is searched; if the value is a string or an array, the directory or directories
            specified will be searched, followed by the <property>include_path</property>.
        </para>

        <para>
            The <varname>$once</varname> argument is a boolean. If <constant>TRUE</constant>,
            <methodname>Zend_Loader::loadFile()</methodname> uses the <acronym>PHP</acronym>
            function <ulink
                url="http://php.net/include"><methodname>include_once()</methodname></ulink>
            for loading the file, otherwise the <acronym>PHP</acronym> function
            <ulink url="http://php.net/include_once"><methodname>include()</methodname></ulink>
            is used.
        </para>
    </sect2>

    <sect2 id="zend.loader.load.class">
        <title>Loading Classes</title>

        <para>
            The static method <methodname>Zend_Loader::loadClass($class, $dirs)</methodname>
            loads a <acronym>PHP</acronym> file and then checks for the existence of the class.
        </para>

        <example id="zend.loader.load.class.example">
            <title>Example of the loadClass() Method</title>

            <programlisting language="php"><![CDATA[
Zend_Loader::loadClass('Container_Tree',
    array(
        '/home/production/mylib',
        '/home/production/myapp'
    )
);
]]></programlisting>
        </example>

        <para>
            The string specifying the class is converted to a relative path
            by substituting underscores with directory separators for your OS, and appending
            '.php'. In the example above, 'Container_Tree' becomes 'Container\\Tree.php' on Windows.
        </para>

        <para>
            If <varname>$dirs</varname> is a string or an array,
            <methodname>Zend_Loader::loadClass()</methodname> searches the directories in
            the order supplied. The first matching file is loaded. If the file
            does not exist in the specified <varname>$dirs</varname>, then the
            <property>include_path</property> for the <acronym>PHP</acronym> environment is
            searched.
        </para>

        <para>
            If the file is not found or the class does not exist after the load,
            <methodname>Zend_Loader::loadClass()</methodname> throws a
            <classname>Zend_Exception</classname>.
        </para>

        <para>
            <methodname>Zend_Loader::loadFile()</methodname> is used for loading, so the
            class name may only contain alphanumeric characters and the hyphen
            ('-'), underscore ('_'), and period ('.').
        </para>

        <note>
            <title>Loading Classes from PHP Namespaces</title>

            <para>
                Starting in version 1.10.0, Zend Framework now allows loading classes from
                <acronym>PHP</acronym> namespaces. This support follows the same guidelines and
                implementation as that found in the <ulink
                    url="http://groups.google.com/group/php-standards/web/psr-0-final-proposal">PHP
                Framework Interop Group PSR-0</ulink> reference implementation.
            </para>

            <para>
                Under this guideline, the following rules apply:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        Each namespace separator is converted to a
                        <constant>DIRECTORY_SEPARATOR</constant> when loading from the file system.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        Each "_" character in the <emphasis>CLASS NAME</emphasis> is converted to a
                        <constant>DIRECTORY_SEPARATOR</constant>. The "_" character has no special
                        meaning in the namespace.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        The fully-qualified namespace and class is suffixed with ".php" when loading
                        from the file system.
                    </para>
                </listitem>
            </itemizedlist>

            <para>
                As examples:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <classname>\Doctrine\Common\IsolatedClassLoader</classname> =&gt;
                        <filename>/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php</filename>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <classname>\namespace\package\Class_Name</classname> =&gt;
                        <filename>/path/to/project/lib/vendor/namespace/package/Class/Name.php</filename>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <classname>\namespace\package_name\Class_Name</classname> =&gt;
                        <filename>/path/to/project/lib/vendor/namespace/package_name/Class/Name.php</filename>
                    </para>
                </listitem>
            </itemizedlist>
        </note>
    </sect2>

    <sect2 id="zend.loader.load.isreadable">
        <title>Testing if a File is Readable</title>

        <para>
            The static method <methodname>Zend_Loader::isReadable($pathname)</methodname>
            returns <constant>TRUE</constant> if a file at the specified pathname exists
            and is readable, <constant>FALSE</constant> otherwise.
        </para>

        <example id="zend.loader.load.isreadable.example">
            <title>Example of isReadable() method</title>

            <programlisting language="php"><![CDATA[
if (Zend_Loader::isReadable($filename)) {
    // do something with $filename
}
]]></programlisting>
        </example>

        <para>
            The <varname>$filename</varname> argument specifies the filename to
            check. This may contain path information.
            This method is a wrapper for the <acronym>PHP</acronym> function
            <ulink url="http://php.net/is_readable"><methodname>is_readable()</methodname></ulink>.
            The <acronym>PHP</acronym> function does not search the
            <property>include_path</property>, while
            <methodname>Zend_Loader::isReadable()</methodname> does.
        </para>
    </sect2>

    <sect2 id="zend.loader.load.autoload">
        <title>Using the Autoloader</title>

        <para>
            The <classname>Zend_Loader</classname> class contains a method you can register with the
            <acronym>PHP</acronym> SPL autoloader. <methodname>Zend_Loader::autoload()</methodname>
            is the callback method. As a convenience, <classname>Zend_Loader</classname> provides
            the <methodname>registerAutoload()</methodname> function to register its
            <methodname>autoload()</methodname> method. If the <property>spl_autoload</property>
            extension is not present in your <acronym>PHP</acronym> environment, then the
            <methodname>registerAutoload()</methodname> method throws a
            <classname>Zend_Exception</classname>.
        </para>

        <example id="zend.loader.load.autoload.example">
            <title>Example of registering the autoloader callback method</title>

            <programlisting language="php"><![CDATA[
Zend_Loader::registerAutoload();
]]></programlisting>
        </example>

        <para>
            After registering the Zend Framework autoload callback, you can
            reference classes from Zend Framework without having to load
            them explicitly. The <methodname>autoload()</methodname> method uses
            <methodname>Zend_Loader::loadClass()</methodname> automatically when you
            reference a class.
        </para>

        <para>
            If you have extended the <classname>Zend_Loader</classname> class, you can give an
            optional argument to <methodname>registerAutoload()</methodname>, to specify
            the class from which to register an <methodname>autoload()</methodname> method.
        </para>

        <example id="zend.loader.load.autoload.example-extended">
            <title>Example of registering the autoload callback method from an
                extended class</title>

            <para>
                Because of the semantics of static function references in <acronym>PHP</acronym>,
                you must implement code for both <methodname>loadClass()</methodname>
                and <methodname>autoload()</methodname>, and the <methodname>autoload()</methodname>
                must call <methodname>self::loadClass()</methodname>. If your
                <methodname>autoload()</methodname> method delegates to its parent to
                call <methodname>self::loadClass()</methodname>, then it calls the
                method of that name in the parent class, not the subclass.
            </para>

            <programlisting language="php"><![CDATA[
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');
]]></programlisting>
        </example>

        <para>
            You can remove an autoload callback. The
            <methodname>registerAutoload()</methodname> has an optional second argument,
            which is <constant>TRUE</constant> by default. If this argument is
            <constant>FALSE</constant>, the autoload callback is unregistered from the
            SPL autoload stack.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
