<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="learning.autoloading.usage">
    <title>Podstawowe użycie autoloadera</title>

    <para>
        Po krótkim opisie samej idei autoloadera jak i konwencji oraz celi związanych z
        jego implementacją w Zend Framework można przejść do opisu użycia
        <classname>Zend_Loader_Autoloader</classname>.
    </para>

    <para>
        W najprostszym przypadku należy dołączyć plik z definicją klasy i uzyskać dostęp do obiektu.
        <classname>Zend_Loader_Autoloader</classname> jest singletonem (co jest uwarunkowane
        autoloaderem <acronym>SPL</acronym>, który jest pojedynczym zasobem) więc do uzyskania
        jego instancji należy użyć metody <methodname>getInstance()</methodname>.
    </para>

    <programlisting language="php"><![CDATA[
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
]]></programlisting>

    <para>
        Domyślnie spowoduje to automatyczne dołączanie dowolnych klas zawierających prefiks 
        przestrzeni nazw "Zend_" oraz "ZendX_" pod warunkiem, że znajdują się w katalogu zawartym w
        <property>include_path</property>.
    </para>

    <para>
        Co się dzieje w przypadku gdy wymagane jest użycie innych przestrzeni nazw? Najlepszym i
        najłatwiejszym sposobem jest wywołanie metody <methodname>registerNamespace()</methodname>.
        Można do niej przekazać pojedynczy prefiks przestrzeni nazw lub ich całą tablicę:
    </para>

    <programlisting language="php"><![CDATA[
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace('Foo_');
$loader->registerNamespace(array('Foo_', 'Bar_'));
]]></programlisting>

    <para>
        Alternatywnie można skonfigurować <classname>Zend_Loader_Autoloader</classname> aby działał
        jako autoloader awaryjny ("fallback" autoloader). To oznacza, że będzie próbował
        działać dla każdej używanej klasy niezależnie od jej prefiksu przestrzeni nazw.
    </para>

    <programlisting language="php"><![CDATA[
$loader->setFallbackAutoloader(true);
]]></programlisting>

    <warning>
        <title>Nie należy używać autoloadera awaryjnego</title>

        <para>
            Użycie <classname>Zend_Loader_Autoloader</classname> jako autoloadera awaryjnego może
            być kuszące ale nie jest rekomendowane.
        </para>

        <para>
            Wewnętrznie <classname>Zend_Loader_Autoloader</classname> używa
            <methodname>Zend_Loader::loadClass()</methodname> do dołączania definicji klas. Ta
            metoda używa <methodname>include()</methodname> do załadowania danego pliku z klasą.
            Funkcja <methodname>include()</methodname> zwraca wartość <constant>FALSE</constant>
            w przypadku niepowodzenia a dodatkowo wysyła błąd ostrzeżenia <acronym>PHP</acronym> co
            może prowadzić do następujących konsekwencji:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    Jeśli włączona jest opcja <property>display_errors</property> to ostrzeżenie
                    zostanie dołączone do wyniku działania funkcji.
                </para>
            </listitem>

            <listitem>
                <para>
                    W zależności od wybranego poziomu opcji <property>error_reporting</property>
                    może powodować bałagan w logach.
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Istnieje możliwość wyłączenia wyświetlania komunikatów błędów przez autoloader
            (opisana w dokumentacji <classname>Zend_Loader_Autoloader</classname>) ale należy
            pamiętać iż działa to tylko w przypadku włączenia opcji
            <property>display_errors</property>. Plik z logami błędów i tak będzie przechowywał
            wszystkie komunikaty. Z tego powodu zalecane jest używanie prefiksów przestrzeni nazw
            i powiadomienie o nich autoloadera.
        </para>
    </warning>

    <note>
        <title>Prefiksy przestrzeni nazw a przestrzenie nazw PHP</title>

        <para>
            W momencie powstawania tego dokumentu istnieje stabilna wersja
            <acronym>PHP</acronym> 5.3. Od tego wydania <acronym>PHP</acronym> oficjalnie oferuje
            pełne wsparcie dla przestrzeni nazw.
        </para>

        <para>
            Zend Framework uprzedził <acronym>PHP</acronym> 5.3 pod tym względem.
            Wewnątrz dokumentacji Zend Framework, jeśli jest mowa o "przestrzeniach nazw" to
            odnosi się to do prefiksów klas wskazujących na aplikację, twórcę lub firmę.
            Dla przykładu, wszystkie nazwy klas w Zend Framework mają prefiks "Zend_" - to jest
            "przestrzeń nazw" używana przez firmę Zend.
        </para>

        <para>
            Planowane jest wprowadzenie obsługi natywnych przestrzeni nazw <acronym>PHP</acronym>
            do autoloadera w przyszłych wersjach Zend Framework. Będzie to możliwe od wersji 2.0.0.
        </para>
    </note>

    <para>
        Jeśli deweloper posiada własny autoloader (np. pochodzący z innej biblioteki, która jest
        używana równolegle), który powinien zostać użyty z Zend Framework to można to uczynić za
        pomocą metod klasy <classname>Zend_Loader_Autoloader</classname> o nazwach
        <methodname>pushAutoloader()</methodname> oraz <methodname>unshiftAutoloader()</methodname>.
        Powyższe metody dopiszą podane funkcje do listy autoloaderów (która jest uruchamiana przed
        wewnętrznymi mechanizmami Zend Framework) odpowiednio na koniec bądź na początek.
        Takie podejście oferuje następujące korzyści:
    </para>

    <itemizedlist>
        <listitem>
            <para>
                Każda z tych metod przyjmuje drugi, opcjonalny argument - prefiks przestrzeni nazw.
                Można go użyć do wskazania aby podany autoloader był używany jedynie do dołączania
                klas zawierających podany prefiks. Jeśli dana klasa go nie posiada to autoloader nie
                zostanie uruchomiony - takie podejście może znacznie zwiększyć wydajność. 
            </para>
        </listitem>

        <listitem>
            <para>
                Jeśli zajdzie potrzeba manipulowania rejestrem funkcji
                <methodname>spl_autoload()</methodname>, każdy autoloader, który stanowi
                odwołanie do metody klasy może powodować problemy. Dzieje się tak ponieważ funkcja
                <methodname>spl_autoload_functions()</methodname> nie zwraca tych samych instancji
                obiektów (tylko ich kopie).
                <classname>Zend_Loader_Autoloader</classname> nie posiada takich wad.
            </para>
        </listitem>
    </itemizedlist>

    <para>
        W powyższy sposób można użyć każdego poprawnego odwołania do funkcji <acronym>PHP</acronym>
    </para>

    <programlisting language="php"><![CDATA[
// Dołączenie funkcji 'my_autoloader', która zajmuje się klasami
// z prefiksem 'My_' na koniec listy autoloaderów
$loader->pushAutoloader('my_autoloader', 'My_');

// Dołączenie statycznej metody Foo_Loader::autoload(), która zajmuje
// się klasami z prefiksem 'Foo_' na początek listy autoloaderów
$loader->unshiftAutoloader(array('Foo_Loader', 'autoload'), 'Foo_');
]]></programlisting>
</sect1>
