Symfony2 Framework Learning Notes HTTP cache usage Detailed _php example

Source: Internet
Author: User
Tags gmt time zone datetime md5 varnish

This example describes the Symfony2 framework HTTP cache usage. Share to everyone for your reference, specific as follows:

The nature of rich Web applications means their dynamics. No matter how efficient your application is, there is always a lot of cost per request compared to static files. For most web programs, this is nothing. Symfony2 is very brisk, and whenever you make a serious overload request, each request will be quickly answered without any pressure on your server. But as your site grows, the load will become a serious problem. Processing of each request should be performed only once. This is what the cache really wants to achieve.

The cache standing on the shoulders of giants:

The most effective way to improve the efficiency of an application is to cache all the output of a page and then allow subsequent requests to bypass the entire application. Of course, this is not always possible for highly dynamic sites. The Symfony2 caching system is more specific because it relies on the simple, powerful HTTP cache defined in the HTTP specification. Without reinventing the new caching method, Symfony2 embraced the criteria for defining basic communication on the Web. Once you understand the underlying HTTP checksum expiration caching pattern, you will have a complete grasp of the Symfony2 caching system.

First step: A gateway cache, or reverse proxy. is an opposing layer sitting in front of your application. The reverse proxy cache comes from your application's response and uses these cached responses to reply to some requests before they reach your application. SYMFONY2 provides its own reverse proxy and can use any other reverse proxy.

Step two: The HTTP cache header is used to communicate with the gateway cache and any other caches that are located between the customer and your application. SYMFONY2 provides default behavior and a powerful interface for caching header interaction.

The third step: HTTP timeout and checksum are used to determine whether a cached content is fresh and stale in two modes.

Step Fourth: ESI (Edge Side Includes) allows the HTTP cache to be used for isolated cache page fragments (even nested fragments). With ESI, you can even cache a full page for 60 minutes. But an inline sidebar cache is only 5 minutes.

Using Gateway Caching

When using HTTP caching, the cache is completely detached from your application, which is located between your requesting client and the application. The caching job is to receive requests from the client and pass them back to your application. It will also receive the response from your application and transfer it to the client. It can be said to be the intermediary between your application and the requesting client-response interaction.

In this way, the cache saves every response that is considered "cacheable". When the same request comes again, the cache responds directly to the requesting client with its cached response, ignoring your application entirely. This type of caching is the HTTP gateway cache. There are many such caches, such as varnish,squid in reverse proxy mode and SYMFONY2 reverse proxy.

Cache type

A gateway cache is not the only type of cache. In fact, there are three different types of caching that intercept and use the HTTP cache headers emitted by your application. They are:

Browser caching (Browser caches): Browsers have their own local cache, which plays a major role when you click the previous step or view pictures and other network assets.

Proxy caches: A proxy cache is a shared cache of multiple people located after one person. Most of them are large companies or ISP installations to reduce latency and network congestion.

Gateway Cache (gateways caches): Like a proxy, it is also a shared cache but is located on the server side. Typically, network administrators install them, making the site more scalable, reliable, and efficient. Gateway caching is sometimes referred to as reverse proxy caching, proxy caching, or HTTP accelerators.

SYMFONY2 Reverse Proxy

Symfony2 has a reverse proxy (also known as a gateway cache) written in PHP. When it is turned on, the cached response reply from your application will begin to be cached immediately. Install it also as easy. Each new Symfony2 application has a pre-configured cache kernel (AppCache) that contains a default appkernel. The cache kernel is a reverse proxy. To turn on caching, modify the front-end controller code to use the cache kernel:

require_once __dir__. ' /.. /app/bootstrap.php.cache ';
Require_once __dir__. ' /.. /app/appkernel.php ';
Require_once __dir__. ' /.. /app/appcache.php ';
Use Symfony\component\httpfoundation\request;
$kernel = new Appkernel (' prod ', false);
$kernel->loadclasscache ();
Use AppCache to wrap the default Appkernel
$kernel = new AppCache ($kernel);
$kernel->handle (Request::createfromglobale ())->send ();

The cache kernel immediately acts as a reverse proxy, and the cache is sent back to the requesting client by a reply from your application.

Note that the cache kernel has a special getlog () method that returns a string that can indicate what happened at the cache level.

You can debug and validate your caching policies in the development environment.

Error_log ($kernel->getlog ());

The AppCache object is a reasonable default configuration, but you can also set the option to tune it by overriding the GetOptions () method.

app/appcache.php use
Class AppCache extends HttpCache
  protected function getoptions ()
    array (
      ' debug '         = > False,
      ' Default_ttl '      => 0,
      ' private_headers '    => Array (' Authorization ', ' Cookie '),
      ' Allow_reload '      => false,
      ' Allow_revalidate '    => false,
      ' stale_while_revalidate ' = > 2,
      ' Stale_if_error '     =>,

Note that no matter how the GetOptions () method is rewritten here, the debug option will automatically set the debug value of the wrapped Appkernel.

Here are some of the important options:

Default_ttl: When no explicit refresh information is provided in the reply, a buffer entity should be considered fresh in time seconds. An explicit setting of Cache-control or Expires headers overrides this parameter value. The default value is 0.
Private_headers: request Header Group, it triggers "private" cache-control behavior in reply, whether the reply is through the Cache-control instruction explicit declaration is public or private. Defaults to authorization and cookies.
Allow_reload: Specifies whether the client is allowed to force the cache to reload by specifying a Cache-control "no-cache" instruction in the request. When set to true, it conforms to the RFC2616 specification. The default value is False.
Allow_revalidate: Specifies whether the client is allowed to force a cache checksum by specifying a Cache-control "max-age=0" instruction in the request. When set to true, it conforms to the RFC2616 specification. The default value is False.
Stale_while_revalidate: Specifies a default number of seconds (the interval is seconds because the reply TTL precision is 1 seconds) and can return a stale reply immediately (default is 2) when the cache is also in the background for the checksum. ; This setting is overridden by the stale-while-revalidate HTTP cache-control extension (RFC 5861).
Stale_if_error: Specifies a default number of seconds (interval is seconds) during which the cache can provide a stale reply when an error is encountered. The default value is 60. This setting is overridden by Stale-if-error HTTP cache-contorl Extensions (RFC5861)

If debug is set to True,symfony2, a X-symfony-cache header is automatically added to the reply to save information about cached clicks and losses.

Conversion from one reverse proxy to another:

SYMFONY2 reverse Proxy is a useful tool for developing your site or deploying your site to a shared host and you can't install anything other than PHP code. But because it's written in PHP, it can't be as fast as a reverse proxy written in C. That's why we recommend using varnish or squid to your operating server. The good news is that it's easy to change from one proxy server to another, simply without you modifying any program code. You can start by using the Symfony2 reverse proxy to upgrade to varnish when the blocking increases.

Note: Symfony2 reverse proxy execution efficiency is independent of application complexity. Because the core of the application is only started when the request needs to be forwarded to it.

HTTP Cache Description:

To play the advantage of the available caching layer, your application must be able to communicate which of its replies can be cached, and when/how the cache will become obsolete. These are implemented by setting the HTTP cache header on the reply (response).

Remember, "HTTP" is simply a simple text language for communication between Web clients and servers. When we say HTTP caching, we say that it allows clients and servers to exchange information-related caches.

HTTP Specifies 4 response cache headers, we need to focus on:


One of the most important is the Cache-control head, which is actually a collection of various cached information.

Cache-control Header

The Cache-control header is the only one whose interior contains a variety of information about whether a response can be cached. Each piece of information is separated by commas.


Symfony provides an abstraction of a Cache-control header, making it more controllable to create.

$response = new Response ();
Mark response as public or private
$response->setpublic ();
$response->setprivate ();
Set private or shared maximum age
$response->setmaxage ();
$response->setsharedmaxage ();
Sets a custom Cache-control instruction
$response->headers->addcachecontroldirective (' must-revalidate ', true);

Public vs Private Response

Both the gateway cache and the proxy cache are considered "shared" caches, because the content they cache is shared by multiple users. If a specific user's response has been incorrectly stored in the shared cache, it may be returned to countless users. Imagine if your account information is cached and then returned to each user who later requests their own account page. To handle this situation, each reply may be set to public or private.

Public instructions to the reply may be saved by private and shared caches.
Private describes all or part of the reply information to a single user, so it cannot be cached in the shared cache.

Symfony carefully default each reply to private. To use the benefits of shared caching (such as Symfony2 reverse proxies), replies must be explicitly set to public.

Security methods:

HTTP caching works only for security methods, such as Get and head. To be secure means that it never changes the state of the application on the server when it is servicing a request. (Of course you can write log information, cache data, etc.). Here are two very reasonable consequences (consequences):

When your application responds to a GET or head request, you will never change the state of your application. Even if you do not use gateway caching, the presence of proxy caching means that any get and head requests may or may not actually reach your server.

Do not expect put,post or delete methods to be cached. These methods are used to imply a change in the state of your application. Caching them will prevent some kind of request from accessing or changing your application.

Caching rules and default settings

HTTP 1.1 allows caching of everything by default unless there is an explicit Cache-control header. In practice, most caches do not perform any caching activities when the request has a cookie, an authorization header, an unsecured method (such as Put,post,delete), or when a request has a redirected code.

When the developer does not make any settings, Symfony2 automatically sets a reasonable and conservative Cache-control header according to the following rules:

If no cache headers are defined (Cache-control,expires,etag or last-modified), Cache-control is set to No-cache, meaning that the response will not be cached.

If the Cache-control is empty (but there is another cache header present), its value is set to Private,must-revalidate;

If at least one Cache-control instruction is set and no ' public ' or ' private ' instruction is explicitly added, Symfony2 automatically adds a private instruction (except where the s-maxage is set).

HTTP Expiration and checksum

The HTTP specification defines two cache models:
An expiration model, you only need to specify how long a response should be considered "fresh" by including a cache-control and/or a expires header. Cache understanding expiration will no longer allow the same request to revert until the cached version reaches its expiration date and becomes "stale" stale.

Validation models are often needed when the pages are real dynamic pages (their presentation often changes). This model caches storage response, but requires the service to response the cache for each request.

The application uses a unique response designator (ETAG header) and/or timestamp (last-modified header) to check whether the page has been released since it was cached.

The goal of both models is to make the application never generate the same response two times by relying on a cache store and returning a "fresh" response.


The expiration model is a more efficient and straightforward model in both models, and it should be possible to be used at all times. When a response is cached using an expiration mode, the cache stores the response and returns it directly to the request without accessing the application until it expires.

The expiration model can be skillfully used with one or two, almost identical, HTTP headers: such as expires or Cache-control.

Expired and Expires headers

According to the HTTP specification, the Expires header field provides a date/time, and after that date or time its response is considered obsolete. The Expires header can be set by the response SetExpires () method. It requires a DateTime instance as an input parameter.

$date = new DateTime ();
$date->modify (' +600 seconds ');
$response->setexpires ($date);

The results of the generated HTTP headers are as follows:

Expires:thu, Mar 16:00:00 GMT

Note that the Setexprise () method automatically converts the date to the GMT time zone as required by the specification.

We note that before the HTTP Specification version 1.1, the source service does not need to send a date header. So caching, such as a browser, may have to rely on its local always to evaluate the expires header, causing the clock to compute the lifecycle. Another limitation of the Expires header is the specification: "http/1.1 service should not send the expires date for more than a year." "

Expired and Cache-control headers

Because of the limitation of expires, you should use Cache-control head instead. Recall that the Cache-control header is used to specify multiple different cache instructions. For expiration, there are two instructions, max-age and s-maxage. The first is used by all caches, while the second is only used for shared caching.

Set a number of seconds, after this second number of response is considered obsolete.
$response->setmaxage ();
Ditto, but only for shared caching.
$response->setsharedmaxage ();
The Cache-control header will use the following format (it may also have other instructions):
cache-control:max-age=600, s-maxage=600


Once the underlying data changes need to update the cached resources immediately, the expiration model becomes inadequate. Under the expiration model, the application is not required to return the updated response until the cache last expires and becomes stale.

The validation model solves the problem. The cache continues to save response under the validation model. The difference is that for each request requested, the cache asks if the response of the application cache is still valid. If the cache is still valid, your application should return a 304 status code and an empty content. This tells the cache that it can return its cached response for the requesting user.

In this model, you mainly save bandwidth because the description does not send two times to the same client (instead of sending a 304 reply instead). However, if you design your application carefully, you may be able to tolerate the minimum data required by 304 response and save the CPU.

The 304 status code means no modification. It is important because it does not contain a full requested content, but rather a lightweight set of guides that tells the cache that it should reply to the request using the version it is now saving. Similar to expiration, there are two different HTTP headers that can be used to implement the checksum model: ETag and last-modifed

Calibration and ETag headers

The ETag header is a string (also called "Entity-tag") that is the unique identifier of a target resource's performance. It is entirely generated and set by your application. For example, if the/about resource is cached, it depends on the date and the return content of your application. A etag, like a handprint, is used to quickly compare whether two different versions of a resource are equivalent.
Like Handprint, each etag must be unique in all representations of the same resource. Let's simply implement a build ETag use MD5 encrypted reply content as content:

Public Function indexaction ()
  $response = $this->render (' MyBundle:Main:index.html.twig ');
  $response->setetag (MD5 ($response->getcontent ()));
  $response->isnotmodified ($this->getrequest ());
  return $response;

The Response::isnotmodified () method compares the ETag sent with the request with the ETag on the Response. If two matches, the method automatically sets the response status code to 304.

This algorithm is very simple and very generic, but you need to create a complete response before you can compute the etag, and the checksum model is a suboptimal choice. In other words, it saves bandwidth and does not save CPU utilization alone.

Symfony2 also supports weak etag by passing in true as the second parameter to the Setetag () method.

Calibration and Last-modified headers

The last-modified header is the second form of the validation model. According to the HTTP specification, the Last-modified header field specifies the date and time at which the source server believes the performance is the last modified version. “
In other words, the application determines whether the cached content is updated after it has been cached based on the cache content. For example, you can use the latest update date for all objects that need to compute the performance of the resource as the value of the last-modified header:

Public Function showaction ($articleSlug)
  $articleDate = new \datetime ($article->getudateat ());
  $authorDate = new \datetime ($author->getupdateat ()); \
  $date = $authorDate > $articleDate? $authorDate: $ Articledate;
  $response->setlastmodified ($date);
  $response->isnotmodified ($this->getrequest ());
  return $response;

The Response::isnotmodified () method compares requests for if-modified-since headers and last-modified headers in Response. If they are equal, response will be set to a 304 status code.

Note that the if-modified-since request header is equal to the last-modified header that is eventually sent to the client-specific resource. This is how the client and the server interact to determine whether the resource has been updated since it was cached.

Use checksums to optimize your code:

The primary purpose of any caching strategy is to reduce the load on the application. In other words, the less your application does to return to 304 response, the better. The Response::isnotmodified () method is done by exposing a simple and effective pattern.

Public funcation showaction ($articleSlug)
  //Get minimum information to compute ETag or last-modified values (based on request, The data is obtained from the database or from a key value to the stored instance.
  $article =///...
  Create a response with a etag and/or a last-modified head
  $response = new Response ();
  $response->setetag ($article->computeetag ());
  $response->setlastmodified ($article->getpublishedat ());
  Check response for the given request is not modified
  if ($response->isnotmodified ($this->getrequest ())) {
    //immediately return 304 Response return
  } else{
    //Do some more work-like getting more data
    $comment =//
    ... Or use the $response you've opened to render a template return
    $this->render (' MyBundle:MyController:article.html.twig ',
        Array (' Article ' => $article, ' comments ' => $comments),

When response has not been modified, isnotmodified () automatically sets the response status code to 304, removes the response content, and removes some headers that do not need to be 304.

Different response responses:

So far, we have assumed that each URI has only one target resource representation. By default, the HTTP cache is executed by using the resource of the URI as the cache key. If two people request a URI for the same cacheable resource, the second user gets the cached version. Sometimes these are not enough, and different versions of a URI need to be cached according to the value of one or more request headers. For example, if the client supports you in compressing the page, there are two representations of any given URI: one is when the client supports compression and one is an unsupported representation. This time the accept-encoding value of the request header determines which to use.

In this case, we need to reply to a specific URI to cache a compressed version and a uncompressed version, and return them based on the requested accept-encoding value. This is through the vary response header, vary is a different head separated by commas, and its value triggers a different representation of the requested resource.


Note that this particular vary header will cache different versions of each resource based on the URI and accept-encoding and user-agent request headers.

The response object provides a clean interface for managing vary headers:

Set a vary head
$response->setvary (' accept-encoding ');
Set multiple vary headers
$response->setvary (Array (' accept-encoding ', ' user-agent '));

The Setvary () method requires a header name or an array of header names to correspond to different response.

Expiration and Validation:

You can of course use checksum expiration in the same response. Because expiration is better than checking, you can easily choose from the two of them. In other words, by using both expiration and checksum, you can instruct the cache to serve the cached content, while the background interval checks to investigate whether the content is still legal.

More Response methods:

The response class provides a number of caching-related methods. Here are some of the main:

Sign response outdated
$response->expire ();
Forced response to return a response
$response->setnotmodified () with no content for 304;

In addition, the HTTP headers that are most relevant to caching can be set by a separate method Setcache ().

Sets the cache parameter through a call
$response->setcache (
  ' etag '     => $etag,
  ' last_modified ' => $date,
  ' Max_age '    =>,
  ' s_maxage '   =>, ' public
  '    => true,
  //' private '  => True,

Using ESI (Edge Side Includes)

Gateway caching is a great way to improve the efficiency of your site's execution. But they have a limit: only the entire page can be cached. If you don't want to cache the entire page or some part of the page is dynamic, you're less fortunate.

Fortunately, Symfony2 provides a solution for these situations, based on ESI technology. It allows a different caching strategy for the portion of the page to be specified than the home page.

The ESI Spec description tag allows you to embed your page and communicate with the gateway cache. Only one tag, include, is implemented in Symfony2, because this is the only label that can be used outside the Akami context.


Notice from this example that each ESI tag has a fully qualified URL. An ESI tag represents a page fragment that can be obtained from a given URL.

When the request is processed, the gateway cache retrieves the entire page from its cache or requests a reply from the application behind it. In other words, the gateway cache fetches both the included page fragment from the cache and then gets the page fragment of the reply request from the application behind it. When all ESI tags are parsed, the gateway cache merges each ESI content onto a home page and returns the final content to the client. All of this transparently happens at the gateway cache level (outside of your program). You will see that if you select ESI tags, Symfony2 makes this process of containing them almost effortless.

Using ESI in Symfony2

First, using ESI requires confirmation to be turned on in your application configuration.

YAML format:

# app/config/config.yml
  ... ESI: {enabled:true}

XML format:

<framework:config ...>
  <framework:esi Enabled= "true"/>

PHP Code format:

$container->loadfromextension (' framework ', array (
  ') ESI '  => Array (' enabled ' => true))

Now suppose we have a page that is relatively static except for a news ticker at the bottom of the content. With ESI, we can cache the news ticker machine independent of other parts of the page.

Public Function indexaction ()
  $response = $this->render (' MyBundle:MyController:index.html.twig ');
  $response->setsharedmaxage ();
  return $response;

In this example, we give a full page cache period of 10 minutes. Next, the news ticker is included in the template by embedding an action. This is accomplished by render help. Because the embedded content is from another page, Symfony2 uses a standard render help to configure the ESI tag:

Twig format:

{% Render ' ...: News ' with {}, {' Standalone ': true}%}

PHP Format:

<?php echo $view [' Actions ']->render (' ...: News ', Array (), Array (' standalone ' => true)?>

By setting standalone to true, tell Symfony2 that the action should be rendered as an ESI tag.

You may wonder why you should use a helper method instead of directly writing the ESI tag. This is because using the helper allows your application to work even if no gateway cache is installed. Let's take a look at how it works.

When standalone is False (also the default), Symfony2 merges the included page content to a home page before sending response to the client.

However, when standalone is true, and if Symfony2 discovers that it is talking to a gateway cache that supports ESI, it generates an ESI include tag.

If there is no gateway cache or the gateway cache does not support Esi,symfony2 will only merge the contents of the included Tag page to a major one as it does when standalone is false.

An embedded action can now specify its own caching rules, completely independent of the home page.

Public Function newsaction ()

With ESI, the entire page cache will remain valid for 600 seconds, but the news build cache will last for only 60 seconds.

A prerequisite for ESI is that an embedded action can be accessed through a URL so that the gateway cache can acquire it independently of the other parts of the page. Of course, an action cannot be accessed through a URL unless a route points to it. Symfony2 is responsible for this through a common routing and controller.

For ESI to contain tags to work properly, you must define _internal routing:

YAML format:

# app/config/routing.yml
  resource: "@FrameworkBundle/resources/config/routing/internal.xml"
  prefix:  /_internal

XML format:

<!--app/config/routing.xml--> <?xml version= "1.0" encoding= "UTF-8"?> "<routes xmlns=
" http:/ / "
  xmlns:xsi=" "
  xsi:schemalocation = "Http://" >
  <import Resource= "@FrameworkBundle/resources/config/routing/internal.xml" prefix= "/_internal"/>

PHP Code format:

app/config/routing.php use
Use Symfony\component\routing\route;
$collection->addcollection ($loader->import (' @FrameworkBundle/resources/config/routing/internal.xml ', '/_ Internal '));
return $collection;

Because routing allows all the action to be accessed through a URL, you can protect it by using the Symfony2 Firewall (which allows access to your reverse proxy IP range) content.

One of the big advantages of caching policies is that you can make your applications as dynamic as possible while minimizing the need to touch applications.

Once you start using ESI, keep in mind that you must use the S-maxage directive instead of max-age. Because the browser accepts only aggregated resources, it does not know subcomponents, so it caches the entire page according to the max-age instruction. That's what you don't want it to do.

Two or two useful options supported by the render helper:
ALT: The ALT attribute used as an ESI tag, which allows you to specify an alternate URL when SRC is not found.
Ignore_errors: If set to true, a onerror property is added to ESI and the property value is set to continue, and in a failure event, the gateway cache will silently remove the ESI tag.

Cache Expiration:

"There are two major challenges in computer science: caching failures and naming things"---Phil karlton

You never need to cache data because the expiration is already considered in the HTTP caching model. If you use checksums, you never need to validate anything by definition; If you use a resource that expires and fails, it means you set a future expiration date. Because failure in any type of reverse proxy is a top-level specification, you can switch between reverse proxies without changing any application code if you don't worry about failure.

In fact, all of the reverse proxies provide a way to clear the cached data, but you need to avoid using them as much as possible. The most standard way to clear the cache for a given URL is by specifying the HTTP method of the request for purge.

Here's how to configure the Symfony2 reverse proxy support Purge HTTP method:

app/appcache.php use
Class AppCache extends HttpCache
  protected function invalidate (Request $request)
    if (' PURGE '!== $ Request->getmethod ()) {return
      parent::invalidate ($request);
    $response = new Response ();
    if (! $this->getstore ()->purge ($request->geturi ())) {
      $response->setstatuscode (404, ' not purged ');
    } else {
      $response->setstatuscode (' purged ');
    return $response;

Note that you must protect your purge HTTP method to avoid any person using certain methods to erase your cached data.


Symfony2 is designed to follow a proven road rule: HTTP. caching is no exception. Mastering the Symfony2 caching system means familiarizing yourself with HTTP caching patterns and using them effectively.

This means that you can't just rely on symfony2 documents and code samples, you have to understand the broader knowledge about HTTP caching and gateway caching, such as varnish.

I hope this article will help you with the PHP program design based on Symfony framework.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.