3
votes

After reading caching behaviour of symfony 1.4.. i came to know that symfony 1.4 is not considering user session for caching templates..

now, the situation is, i have several templates that have some part of code that depends on user session.. let's say if user is authenticated he has a facility to ask question in product listing... now how should i cache this template file... one thing i know that creating separate template for all that session code blocks and setting cache false to it. but i want to know other smart ways if you have...

Thank you, Hardik

5

5 Answers

3
votes

Warning: The symfony cache mechanism does not support private caching. Incorrectly applied it will result in leaked data!

Do not use cache.yml

Do not use cache.yml at all for content that depends on the session in any way, especially content that is restricted by the session. cache.yml unconditionally displays the first version a user has seen to all others, logged in or not.

Use a conditional cache filter

Instead, create a conditional cache filter. The following will cache every page, and hence display the version of the first user, for all users that have the credential myCredential.

// apps/myApp/lib/conditionalCacheFilter.php
class conditionalCacheFilter extends sfFilter() {

  public function execute($filterChain) {
    $context = $this->getContext();
    $user = $context->getUser();
    if ($user->isAuthenticated() && $user->hasCredential('myCredential')) {
      foreach ($this->getParameter('pages') as $page) {
        $context->getViewCacheManager()->addCache($page['module'], $page['action'], array('lifeTime' => 300));
      }
    }
    // Execute next filter
    $filterChain->execute();
  }
}


# filters.yml
conditionalCache:
  class: conditionalCacheFilter
  param:
    pages:
      - { module: myModule, action: myAction }

cache: ~

Use case

This is useful for a data heavy page shown to only users with a certain credential, but all users get the same page. A collection of credential specific statistics pages is a good example.

Alternative use

You may also directly specify pages to be added in the cache to the filter. It could be a useful failsafe to still explicitly activate the filter for certain pages only.

// apps/backend/lib/conditionalCacheFilter.php
$context = $this->getContext();
$user = $context->getUser();
if ($user->isAuthenticated() && $user->hasPermission()) {
  $context->getViewCacheManager()->addCache('myModule', 'myAction', array(
    'withLayout' => true,
    'lifeTime'   => 3600,
  ));
}

#filters.yml
conditionalCache:
  class: conditionalCacheFilter
    pages:
      - { module: myModule, action: myAction }

No true private caching

Symfony does not have provisions for a by-user private cache. You should use client side cache control headers with the private setting for this use case. You may also use an nginx reverse proxy or similar setup.

1
votes

you can cache your template in this way

<?php $cache_str='something-that-is-uniq-'.$sf_user->isAuthenticated()?$sf_user->getGuardUser()->getId():'';
<?php if (!cache($cache_str,36000)): ?>
<div> something that you want to cache </div>
  <?php cache_save(); ?>
<?php endif; ?>
0
votes

Hardik as your application becomes more and more complex the best way to have dynamic and cached contents on a page is to use partial and components with their own cache settings. You just need to decouple the main sections creating partial and components to replace all your contents. Then you add this smaller parts to the nameYourTemplateSuccess.php that shouldn't be cached, otherwise all partial/components will be cached.

More on caching partials and components here.

0
votes

I second @dlondero's partial caching with parameters, of which I was unaware until now.

In a past project, I implemented a modified caching filter and manager, which will cache at the action level based on session-based values. This may (?) be more efficient, as it caches the entire result of the action (i.e. not just partials/components)

https://github.com/yitznewton/freerms/blob/master/apps/resolver/lib/view/freermsResolverCacheManager.class.php

https://github.com/yitznewton/freerms/blob/master/apps/resolver/lib/filter/freermsResolverCacheFilter.class.php