session.test + symfony forms incompatibility #872

theycallmeswift opened this Issue Nov 19, 2013 · 7 comments

4 participants


I'm writing some integration tests and I seem to have found an incompatibility between the session.test setup and Symfony forms (with csrf enabled).

I have a route (/users/new) that renders a form:

$form = $app['form.factory']->createBuilder('form', array())
  ->add('Sign Up', 'submit')

return $app['twig']->render('@UserBundle/users/new.html.twig', array(
  'form' => $form->createView(),

In my tests, I click a link that would render that form:

$link = $crawler->filter('.login_area a[href="/users/new"]')->link();
$crawler = $client->click($link);

And that produces the following error:

1) \UserBundle\Tests\Features\UserLoginTest::testVisitorViewsSignUp
session_start(): Cannot send session cookie - headers already sent by (output started at /vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php:298)


I traced it back to the following function in Symfony Form:

protected function getSessionId()
    if (version_compare(PHP_VERSION, '5.4', '>=')) {
        if (PHP_SESSION_NONE === session_status()) {
    } elseif (!session_id()) {

    return session_id();

Basically, Symfony is trying to enable the session for CSRF, but the session is a fake one. We need to somehow set session_status to not be none. Looks like this is specific to 5.4.


Have you got the SessionServiceProvider registered? The FormServiceProvider should use the SessionCsrfProvider if so, which should avoid that problem.


Yes, I do. It's looking like this is a weird ordering issue. If I do this:

$app->register(new Silex\Provider\SessionServiceProvider());
$app['session.test'] = true;
$app->register(new Silex\Provider\FormServiceProvider());

It works. But any other order does not. Also, I'd really prefer if my call to $app['session.test'] = true; was in the function createApplication() {} method instead of in app.php.

The other issue here is that the order priority of the middleware is not clear. This is the second time ordering has been an issue for me as a new user. The docs really need to reflect these kind of intricacies.


The ordering shouldn't really matter, providing you don't access the form services before registering the session provider. This is a general rule for Silex (and Pimple), don't access things until you've finished registering things.


Any thoughts on why I'm running into issues then? I definitely have all three lines in my app. Maybe it's phpunit specific?


Are you accessing $app['form.factory'], or $app['form.extensions'] etc before registering the session service provider? The usual problem is people doing something like this:

$app->register(new FormServiceProvider());
$app['form.extensions'] = array_merge($app['form.extensions'], array(new MyFormExtension()));
$app->register(new SessionServiceProvider());

If you're not doing anything like that, drop in to #silex-php on freenode if you want, you can paste a bit more code etc and we can find out what's going on.


@davedevelopment and I investigated a little further without much luck. The only possible issue fragments we found were:

if ( $env == 'staging' || $env == 'development' ) {
     $app['twig']->addExtension(new Twig_Extensions_Extension_Debug());


$app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
     $twig->addExtension(new Someecards\SomeFramework\TwigExtension\AssetsExtension($app));
     $inlineFragmentRenderer = new InlineFragmentRenderer($app['kernel'], $app['dispatcher']);
     $fragmentRenderer = new EsiFragmentRenderer($app['http_cache.esi'], $inlineFragmentRenderer);
     $fragmentHandler = new FragmentHandler(array($fragmentRenderer, $inlineFragmentRenderer), false);
     $twig->addExtension(new HttpKernelExtension($fragmentHandler));

     return $twig;

Any other insights would be awesome.


@theycallmeswift $app['twig']->addExtension(new Twig_Extensions_Extension_Debug()); accesses Twig (and all its dependencies, which include the form). You should use $app->extend() to register the extension.

On a side note, the Twig_Extensions_Extension_Debug is deprecated. You should use Twig_Extension_Debug available in Twig core since 1.5 (and registered by Silex automatically when $app['debug'] is true IIRC).
and for the FragmentHandler, you should register the HttpFragmentServiceProvider instead of doing the setup by hand

@fabpot fabpot closed this Jun 13, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment