3

I have a cached site which have a form in it which should not be cached. I use ESI for it. When the form is submit I need to get the POST Parameter in my controller. Symfony let me get the Request Parameter 'form' not the real POST Data or is there a good way to get them.

{{ render_esi(controller('MyBundle:Form:staticForm', {'form': 'sidebar'}))}}

Setting them in twig will not work because of Parent Page Cache.

{{ render_esi(controller('MyBundle:Form:staticForm', {'form': 'sidebar', 'request': }))}}

So how to get the post parameter in my controller currently the code shown here only gets me the ESI data:

public function staticFormAction(Request $request) {
    // ..
    $form->handleRequest($request);// will not work because:
    $request->get('firstName'); // is empty when called by ESI

How I can get the Parameters from the Parent Request?

Hacky solution

Currently the only solution I found is for me too hacky
TWIG:

{{ render_esi(controller('ClientWebsiteBundle:Form:staticForm', app.request.request.all|merge({'form': 'sidebar'}), app.request.query.all)) }}

PHP:

$data = ($request->get('myFormName'));
if (count($data)) {
    // Forms uses $request->request
    $request->request->set('myFormName', $data);
    $request->setMethod('POST');
}

Additional

After a little research and look into symfony core code I need to change the ESI to Post so my question is know "How to call ESI as POST method not GET?"

Solution

Using requestStack like Chris Tickner posted seems the post solution.

Alexander Schranz
  • 2,154
  • 2
  • 25
  • 42

2 Answers2

3

ESI is an edge-side include, which means it is not designed to handle POST data. By default, reverse proxies like Varnish or Symfony's HttpCache kernel, see the ESI as a URL ("/_proxy?_controller=x&params=etc") which they include by GET-ing it from your app. This is why you are finding this difficult.

However, no proxy is going to cache a POST request, so you could, during a POST request, access the master request using the request_stack service.

// if POST
$master_request = $this->get('request_stack')->getMasterRequest();
$form->handleRequest($master_request);

This should do the trick if you are using the Symfony HttpCache.

http://api.symfony.com/2.7/Symfony/Component/HttpFoundation/RequestStack.html

Chris Tickner
  • 2,008
  • 2
  • 20
  • 24
  • Also, for the most part you should probably NOT be putting post data in an ESI. That could be sensitive data that might be cached with your master page. Meaning, all requests will be effectively "POSTING" that same data, due to your hack. Not safe. – Chris Tickner Jan 22 '15 at 03:41
  • with not putting post data in ESI you mean the call of the my render_esi function with app.request...? I think i will not need this when using requestStack. Currently the requestStack works for me on Dev but it seems that my post requests are cached on production, when I got this fixed it seems to be a good solution. – Alexander Schranz Jan 22 '15 at 07:57
1

You can get the full form data using

$data = $form->getData();

Or, for single fields:

$var = $form->get('yourformfieldname')->getData();

Watch out: this is for Symfony >= 2.3, and it would get you two different things:

  • the entity with values populated by the form, if your form have the data-class option enabled (so it's binded to an entity); this will exclude any field with the 'mapping' => false option

  • otherwise, an array with all the form's fields

Alessandro Lai
  • 2,254
  • 2
  • 24
  • 32
  • The problem is the ESI component when not used I can set the form data by: `$form->handleRequest($request);` but when called over ESI I will only get the parameter set in TWIG file not from POST. – Alexander Schranz Jan 21 '15 at 11:40
  • I did have a look at the handleRequest in HttpFoundationRequestHandler only found a hacky solution (added at my post). ESI request is change to GET and the attributes are set as GET attributes which symfony forms cant handle. I did add a hacky solution at my post, but still search for a better solution. The only problems seems to be that the ESI is called as GET instead as POST and so the parameter is set as GET Params not as POST Data :( – Alexander Schranz Jan 21 '15 at 14:10
  • You could use `->setMethod('GET')` on your form from the start – Alessandro Lai Jan 22 '15 at 09:16