Zend Framework 2 config and classmaps

Binnen Zend Framework 2 werk je met heel veel config files die via autoloaders worden geladen. Dit maakt het bijzonder prettig modulair werken maar geeft in productie snel een flinke load. Nu kun je eenvoudig de caching hiervan configureren voor betere performance in productie.

Application.config.php

Ik heb ervoor gekozen te werken met een application_env (zoals ik dat gewend was in Zend Framework 1) om environment gebonden configuraties toe te passen. Globaal ziet mijn config er zo uit (als het gaat om caching en de environment);

$env = getenv('APPLICATION_ENV') ?: 'production';

$array = array(
    'modules' => array(
        'Application',
    ),
    'module_listener_options' => array(
        'module_paths' => array(
            './module',
            './vendor',
        ),
        'config_glob_paths' => array(
            'config/autoload/{,*.}{global,' . $env . '}.php',
        ),
        'cache_dir' => __DIR__ . '/../data/cache/modulecache',
        'config_cache_enabled' =>  true,
        'config_cache_key' =>  $env,
        'module_map_cache_enabled' => true,
        'module_map_cache_key' => $env,
    ),
);

if('development' == $env) {
    $array['module_listener_options']['module_map_cache_enabled'] = false;
    $array['module_listener_options']['config_cache_enabled'] = false;
    array_unshift($array['modules'], 'Whoops');
    array_push($array['modules'], 'BjyProfiler', 'ZendDeveloperTools');
}

return $array;

Dat laatste stukje is beetje een iets minder mooie maar effectieve oplossing om mijn development-omgeving gebonden tools (ZendDeveloperTools, BjyProfiler & Whoops) te laden en de caching, die by default op true staat, uit te zetten. In acceptatie, productie en welke environment dan ook werkt alles wel conform de reguliere config. Dus caching aan en een enviroment-based key.

Autoload_classmap.php

Wel een leuke performance toevoeging. Classmaps die met autoload meekomen zodat Zend niet alles overal hoeft te zoeken. Je kunt ze eenvoudig via de commandline genereren met de, met ZF2 meegeleverde, classmap_generator.php. Deze staat uiteindelijk in de root van je module dus bijv. in dit geval /task/autoload_classmap.php

In je Module.php zet je dan het volgende neer om deze classmap te laden;

    /**
     * @return array
     */
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),
        );
    }

De autoload_classmap.php ziet er ongeveer zo uit (hangt er af van je module, in dit geval ‘task’);

// Generated by ZF2's ./bin/classmap_generator.php
return array(
  'Task\Task'                                   => __DIR__ . '/Task.php',
  'Task\Controller\TaskAdminController'       => __DIR__ . '/src/Task/Controller/TaskAdminController.php',
  'Task\Entity\TaskAdminEntity'               => __DIR__ . '/src/Task/Entity/TaskAdminEntity.php',
  'Task\Form\TaskAdminForm'                   => __DIR__ . '/src/Task/Form/TaskAdminForm.php',
  'Task\InputFilter\TaskInputFilter'          => __DIR__ . '/src/Task/InputFilter/TaskInputFilter.php',
  'Task\Model\TaskAdminModel'                 => __DIR__ . '/src/Task/Model/TaskAdminModel.php',
  'Task\Service\TaskAdminService'             => __DIR__ . '/src/Task/Service/TaskAdminService.php',
);

APC cache en Zend Server CE

Als je op je Zend Server CE kijkt in de extensions lijst zoals die default ingesteld staan zou je vermoeden dan APC erop draait.

Dit blijkt echter niet geheel het geval als je de php.ini bekijkt. De versie die erop staat lijkt een soort port te zijn naar de cache engine van Zend Server zelf. Niet alle commando’s die normaal in APC beschikbaar zijn werken etc.

APC installeren
Paul Kiddie heeft op zijn weblog al redelijk goed uitgezocht hij hij dit kon doen ten behoeve van een file upload progress bar.

  • Ga naar http://downloads.php.net/pierre/
  • Zoek de juiste versie van APC caching die bij je systeem past. In mijn geval was dit php_apc-3.1.5-5.3-nts-vc9-x86.zip (APC versie 3.1.5 voor PHP 5.3, Non-Threading Safe VC9 versie)
  • Plaats php_apc.dll in je zendServer map \lib\phpext\
  • Pas je php.ini (zendServer map \etc\) aan en voeg onderin bij de extensions extension=php_apc.dll toe.
  • Restart je PHP engine en klaar

Als het goed is bevat je phpinfo nu het APC configuratie deel:

Kanttekening

Je PHP log bevat nu een warning.

[20-Nov-2010 15:31:48] PHP Warning:  Module 'apc' already loaded in Unknown on line 0

Dit heeft te maken met de “APC” zoals Zend Server die zelf laadt. Je nu toegevoegde extension botst daar licht mee. Heb wel gekeken naar de opties maar heb nog geen oplossing. De APC request die Zend Server al doet voor je eigen extensies komt mee uit een kant-en-klare extension-dll van Zend Server. Als je hem via de Zend Server configuratietool disabled gooit hij ook gelijk je zelf toegevoegde APC extensie uit de php.ini. Zet je de eigen extension regel er dan weer in dan zet hij ook gelijk die van Zend Server weer aan op één of andere manier.

Update 23 november @ 22:05

We hadden het er vandaag op kantoor nog eens over en Pieter (thnx!) kwam met een briljant idee. Hij kon zich namelijk herinneren ergens in de configs van ZendServer ook nog een file tegengekomen te zijn waarin de oorzaak mogelijk stond.

Hierbij dus alsnog de oplossing voor deze error:

In ZendServer/etc/cfg staat het bestand datacache.ini. Hierin staat:

; When enabled, the Data Cache extension registers APC compatibility methods
zend_datacache.apc_compatibility=1

Als je die parameter op 0 zet ben je er. Op zich ook een erg logische regel om op 0 te zetten als je hem zo leest.