Duże aplikacje napisane w oparciu o Zend Framework zazwyczaj zawierają duży plik konfiguracyjny, niejednokrotnie zapisany w postaci XML. Im większy plik konfiguracyjny, tym wolniej jest on tłumaczony do postaci rozumianej przez PHP. Z tego właśnie względu warto zastosować cache’owanie konfiguracji naszej aplikacji.

Wbrew pozorom nie jest to proces skomplikowany i wymaga jedynie kosmetycznych poprawek w projekcie. Wystarczy utworzyć klasę dziedziczącą po Zend_Application, a w niej przesłonić metodę odpowiedzialną za wczytanie pliku konfiguracyjnego.

class Batman_Application extends Zend_Application
{
    /**
     * @var null|Zend_Cache_Core
     */
    private $_cache = null;

    /**
     * @var null|string
     */
    private $_configFile = null;

    /**
     * @param string $file
     */
    public function setConfigFile($file)
    {
        $this->_configFile = $file;
    }

    /**
     * @return null|string
     */
    public function getConfigFile()
    {
        if($this->_configFile === null) {
            $this->_configFile = APPLICATION_PATH . '/configs/application.ini';
        }
        return $this->_configFile;
    }

    /**
     * @param Zend_Cache_Core $cache
     */
    public function setCache(Zend_Cache_Core $cache)
    {
        $this->_cache = $cache;
    }

    /**
     * @return null|Zend_Cache_Core
     */
    public function getCache()
    {
        if($this->_cache === null) {
            $this->_cache = Zend_Cache::factory(
                'File',
                'File',
                array(
                    'master_files' => array($this->getConfigFile()),
                    'automatic_serialization' => true,
                    'lifetime' => null
                ),
                array(
                    'cache_dir' => APPLICATION_PATH . '/data/cache'
                )
            );
        }
        return $this->_cache;
    }

    protected function _loadConfig($file)
    {
        if($this->_configFile === null) {
            $this->setConfigFile($file);
        }

        $cache = $this->getCache();
        $config = $cache->load('config_cache');
        if(!$config) {
            $config = parent::_loadConfig($file);
            $cache->save($config, 'config_cache');
        }

        return $config;
    }
}

Powyższy przykład korzysta z cache’u File, który automatycznie się odświeża, gdy w pliku konfiguracyjnym zostaną wprowadzone zmiany. Nic nie stoi na przeszkodzie aby to zmienić na dowolny inny cache, podobnie z resztą jak backend. Jeśli mamy dostęp do Memcached lub APC, o wiele lepiej będzie tam przechowywać cache, niż w pliku.

Jedyną zmianę jaką należy wprowadzić w już istniejącym kodzie, to modyfikacja pliku index.php, w którym zmieniamy nazwę klasy Zend_Application, na klasę przez nas utworzoną.

// reszta pliku index.php

require_once 'Zend/Application.php';
require_once 'Batman/Application.php';

// Create application, bootstrap, and run
$application = new Batman_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap()
            ->run();

Zanim jednak zdecydujemy się na cache’owanie konfiguracji, lepiej upewnić się, że taka zmiana nam się opłaci. Może się bowiem tak zdarzyć, iż parsowanie pliku z konfiguracją jest szybsze niż sprawdzenie czy cache jest aktualny.

Pliki z kodem źródłowym znajdziecie na Githubie.

Aktualizacja

W komentarzach melkrom słusznie zauważył, iż plik konfiguracyjny powinien być pobierany ze zmiennej przekazanej do metody _loadConfig. Dodałem taką możliwość do klasy. Wpis oraz projekt na Githubie zostały zaktualizowane do nowej wersji.