Symfony's Two Generated PHP Files

Update: The information in the post below is correct, except for the part where it talks about Symfony have two generated PHP files. It actually has three.

More as a reminder to myself than anything else, it's important to remember a Symfony application has two generated PHP files.

The first is the bootstrap cache file. Despite being a cache file, this does not live in the cache folder. Instead, it lives directly in app/

app/bootstrap.php.cache

This file contains the Symfony Component PHP classes needed to bootstrap a basic Symfony/HttpKernel environment. It lives outside the cache folder because it's environment independent. Put another way, these are the classes that make the environment system possible.

The second generated file is the container class file. Its name/location is dependent on the type of app kernel and the environment you're running in. Most of the time it lives in the following locations for the dev and prod environments.

app/cache/dev/appDevDebugProjectContainer.php
app/cache/prod/appProdProjectContainer.php

This file contains the generated class that implements the container for a specific project. That is, when the framework generates a container file, it looks at the configuration for each bundle and generates a class with methods and configuration that allow a a Symfony programmer to use the container.

For example, when you say

$this->get('logger');

from a controller in Symfony, the framework eventually calls the method

#File: app/cache/dev/appDevDebugProjectContainer.php
protected function getLoggerService()
{
    $this->services['logger'] = $instance = new \Symfony\Bridge\Monolog\Logger('app');

    $instance->pushHandler($this->get('monolog.handler.console'));
    $instance->pushHandler($this->get('monolog.handler.main'));
    $instance->pushHandler($this->get('monolog.handler.debug'));

    return $instance;
}

By generating a container class with these methods pre-defined, the framework code avoids the performance overhead of looking up the configured class names for every service call, as well as some of the PHP overhead involved in using magic methods like __call.

Regenerating

If you're creating new services in Symfony, you'll often need to re-generate you container file. Doing so is as simple as clearing your Symfony cache — the Symfony kernel will regenerate these files automatically. If you're curious, the code that does this starts here

#File: vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php
protected function initializeContainer()
{
    $class = $this->getContainerClass();
    $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
    $fresh = true;
    if (!$cache->isFresh()) {
        $container = $this->buildContainer();
        $container->compile();
        $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());

        $fresh = false;
    }

    require_once $cache;

    $this->container = new $class();
    $this->container->set('kernel', $this);

    if (!$fresh && $this->container->has('cache_warmer')) {
        $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
    }
}

Regenerating the bootstrap cache file is a little trickier. In theory, only a Symfony internals developer ever needs to regenerate this file. However, if you're like me, you'll often end up dropping some var_dump's in core system files to figure out what the heck's going on with a bug. This, in turn, means you can sometimes accidentally delete something important and need to regenerate the file.

Fortunately, while it takes a little digging, it is possible to generate the bootstrap cache file. Symfony ships with a file named build_bootstrap.php. Just run this from the console, and your file should be regenerated.

./vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/bin/build_bootstrap.php

This file has a history of moving around, but a quick

$ find . -name 'build_bootstrap.php`

should point you towards the correct file. Finally, if you're using composer to manage your Symfony project, running

$ composer.phar update

should automatically regenerate the bootstrap cache file.