Question

I'm trying to speed up my site by taking advantage of the new HTTP cache features in CakePHP 2.1:

class ArticlesController extends AppController {
    public function view($id) {
        $article = $this->Article->find(
            'first',
            array('conditions' => array('Article.id' => $id))
        );

        $this->response->modified($article['Article']['modified']);
        $this->set(compact('article'));
    }
}

Caching works fine, but does not distinguish between different users (i.e. if a user logs in and visits a page that was already cached, the previously cached page is displayed, and user-specific content is not shown). I'd like one of the following to happen:

  • Cache discriminates between different users and stores a separate cache for each user
  • Caching is disabled if a user is logged in (the user login is only used for admin purposes)

I've tried adding

if (AuthComponent::user('id')) {
    $this->disableCache();
}

But this doesn't seem to solve the problem

Does anyone know how to get this to work, or am I doing something fundamentally wrong?

Was it helpful?

Solution

You could try the etag caching method and generate a hash based on the article id and user id.

See http://book.cakephp.org/2.0/en/controllers/request-response.html#the-etag-header

The Etag header (called entity tag) is string that uniquely identifies the requested resource. It is very much like the checksum of a file, caching will compare checksums to tell whether they match or not.

To actually get advantage of using this header you have to either call manually CakeResponse::checkNotModified() method or have the RequestHandlerComponent included in your controller:

<?php
public function index() {
    $articles = $this->Article->find('all');
    $this->response->etag($this->Article->generateHash($articles));
    if ($this->response->checkNotModified($this->request)) {
        return $this->response;
    }
    ...
}

OTHER TIPS

I thought I'd post the solution(s) I eventually used, in case it helps anyone.

To disable caching completely for logged in users:

class ArticlesController extends AppController {
    public function view($id) {
        $article = $this->Article->find(
            'first',
            array('conditions' => array('Article.id' => $id))
        );

        if (!AuthComponent::user('id')) {
            $this->response->etag($this->Article->generateHash($article));
        }

        $this->set(compact('article'));
    }
}

To have a separate cache for each user (and for the case when no-one is logged in):

class Article extends AppModel {
    public function generateHash($article) {
        if (AuthComponent::user('id')) {
            return md5(AuthComponent::user('id') . '-' . $article['Article']['modified']);
        } else {
            return md5($article['Article']['modified']);
        } 
    }   
}

class ArticlesController extends AppController {
    public function view($id) {
        $article = $this->Article->find(
            'first',
            array('conditions' => array('Article.id' => $id))
        );

        $this->response->etag($this->Article->generateHash($article));

        $this->set(compact('article'));
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top