Categories
Resources Web Development

How to create a cookie in Symfony 5.0+ and render a template in a controller

First what I wanted to do was create a cookie in a Controller and display a template at the same time. Sort of like when a user visits a page you set a page count or something. The documentation doesn’t really show an example, you are expected to know it via “common sense” apparently according to one smartass.

There is more than one way I have discovered over time. Apparently you can use render the same way I show using renderView.

Below is the Symfony Cookie class create method comment/documentation. This is all of the values you can supply when creating a cookie.

 /**
     * @param string                        $name     The name of the cookie
     * @param string|null                   $value    The value of the cookie
     * @param int|string|\DateTimeInterface $expire   The time the cookie expires
     * @param string                        $path     The path on the server in which the cookie will be available on
     * @param string|null                   $domain   The domain that the cookie is available to
     * @param bool|null                     $secure   Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS
     * @param bool                          $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
     * @param bool                          $raw      Whether the cookie value should be sent with no url encoding
     * @param string|null                   $sameSite Whether the cookie will be available for cross-site requests
     *
     * @throws \InvalidArgumentException
     */

If you create a cookie like this :

$response->headers->setCookie(Cookie::create('foo', 'bar'));

Then the cookie will only live/exist until the user closes their browser(unless your browser restores from your last session). You must supply an expires time to make it persist beyond closing the browser. Providing an expires time gives you better control over when the cookie expires due to the above mentioned browser restore issue which will restore cookies that should have died on browser close.

You can also create the cookie then pass it to setCookie() like this.

 $response = new Response();
        $expires = time() + 36000;
        $cookie = Cookie::create($cookieName, $cookieValue,  $expires);
        //$cookie = $response->headers->setCookie(Cookie::create('foo', 'bar'));
        $response->headers->setCookie($cookie);

        $content = "<html><body><h1>Learning symfony cookie creation techniques?</h1></body></html>";
        $response->setContent($content);
        $response->headers->set('Content-Type', 'text/html');
        return $response;

Here I set the expires to a number,  time() returns a linux/unix timestamp and I added 36000 seconds or 10 hours to it. This cookie will exist until the user refreshes their page or clicks a link in 10 hours from creation. However long you want it to live you add that many seconds. Or you could create a date using PHP DateTime as you can pass a DateTime object to the expires position. You then use the methods of DateTime to increase the time to a period in the future and pass the DateTime object after calling the methods to do so.

Side Note : in the above code, you can create a cookie without the $response->setContent() call. I do that with the body tag so that the profiler will show up at the bottom of the page for debugging.

That code goes inside a controller method for the requested route by the way. Usually you use the render() method inside a controller to send a response, which renders the template and sends it in a response. You can also use renderView to do the same thing and capture the value in a variable then use setContent or just make the renderView call right in setContent. I know that works. You can also store the returned value from render the same way.  But no matter how you do it, you must return the response object, the very last line. You can find all the methods of the Response class here in the source code.

If you wanted to render a view which requires variables to be sent you do it like this and capture the output of renderView().


 $content = $this->renderView('blog/display_article.html.twig', [
            'title' => $title,
            'article' => $article,
            'tags' => implode(', ', $tags),
            'tagLinks' => $links,
            'edit' => $editLink,
            'affiliateUrl' => $affiliateUrl,
            'backButton' => $backButton
        ]);

Note : do not just use php setcookie or setrawcookie. The reason is they start sending output headers to the browser, which may interfere with how symfony works. You probably won’t notice in a browser, but you may get errors when testing your controllers with functional tests etc.

Personally I created a huge class which extends DateTime which has all kinds of methods for adding days, hours, removing them and doing other math. I’d share it on github but it has bugs since I wrote it way back in version 5 of php in 2012. Some changes were made to DateTime and I haven’t had time to review them all and hunt down the changes that need to be made yet. I’ll probably do it and add it to github eventually.  But for now I use time() + seconds. It’s not the best solution but it works and I only need this one cookie.

And another person found me more hidden docs about cookies, I wish I had this days ago.

As another note. Any values you put in a cookie you must sanitize before trying to use them in any way since users can access and change regular cookie values.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.