Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions http_cache/expiration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,92 @@ servers should not send ``Expires`` dates more than one year in the future."
the ``Expires`` header value is ignored when the ``s-maxage`` or ``max-age``
directive of the ``Cache-Control`` header is defined.

Applying Cache Conditionally
----------------------------

.. versionadded:: 8.1

The ability to apply the ``#[Cache]`` attribute conditionally was introduced
in Symfony 8.1.

You can use the ``if`` option to conditionally apply the ``#[Cache]`` attribute.
This option accepts either a closure or an :doc:`ExpressionLanguage </components/expression_language>`
expression that must return a boolean value:

.. configuration-block::

.. code-block:: php-attributes

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\Cache;
// ...

// Using a closure
#[Cache(
public: true,
maxage: 3600,
if: fn (Request $request) => $request->query->has('cache')
)]
public function index(Request $request): Response
{
// ...
}

// Using an expression
#[Cache(
public: true,
maxage: 3600,
if: "request.query.has('cache')"
)]
public function show(Request $request): Response
{
// ...
}

The closure or expression has access to the ``Request`` object and controller
arguments. When the condition evaluates to ``true``, the cache headers are
applied; when it evaluates to ``false``, they are not.

This is particularly useful when:

* You need to enable caching programmatically based on runtime conditions
* Your controller does not return a ``Response`` object directly (e.g. when using
`FOSRestBundle`_ or other libraries that handle view rendering)
* You want to cache based on user authentication, feature flags, or request parameters

Multiple Cache Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~

The ``#[Cache]`` attribute is repeatable, allowing you to define multiple
attributes with different conditions on the same controller:

.. code-block:: php-attributes

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\Cache;
// ...

#[Cache(
public: true,
maxage: 3600,
if: fn (Request $request) => !$request->query->has('preview')
)]
#[Cache(
public: false,
maxage: 0,
if: fn (Request $request) => $request->query->has('preview')
)]
public function article(Request $request): Response
{
// This will cache for 1 hour when preview=1 is NOT in the query string,
// and disable caching when preview=1 IS present
}

Only the first ``#[Cache]`` attribute whose condition evaluates to ``true``
will be applied. If no condition matches, no cache headers will be set by
the attribute.

.. _`expiration model`: https://tools.ietf.org/html/rfc2616#section-13.2
.. _`Calculating Freshness Lifetime`: https://tools.ietf.org/html/rfc7234#section-4.2.1
.. _`Serving Stale Responses`: https://tools.ietf.org/html/rfc7234#section-4.2.4
.. _`FOSRestBundle`: https://github.com/FriendsOfSymfony/FOSRestBundle
Loading