1

I'm having some issues with caching my component output as the user state variables seem to be ignored. I've added them to my controller as follows which works fine when submitting the filter form on the front-end, not so much however when clicking on the next pagination item at which point it just ignores the variables (since they're not in the request).

public function display($cachable = true, $urlparams = array()) {
    $app = JFactory::getApplication();
    $input = $app->input;
    $view = $input->getCmd('view', 'foo');
    $input->set('view', $view);

    $context = 'com_foobar.'.$view;
    if($list = $app->getUserStateFromRequest($context.'.list', 'list')) $urlparams['list'] = $list;
    if($filter = $app->getUserStateFromRequest($context.'.filter', 'filter')) $urlparams['filter'] = $filter;

    parent::display($cachable, $urlparams);

    return $this;
}

How do I make my component display the correct cached output, taking state variables into consideration?

Thanks!

1
  • The $cachable parameter which you pass to super class display method is a boolean flag to let Joomla core know whether or not it should cache your components views the same way core component views are cached if the caching plugin is enabled. For a highly customized caching solution I would consider moving this logic to the model for two reasons. First and foremost, you would be able to affect any pagination or table sorting requests based on the caching needs and secondly, Joomla core caching allows for very little customization. Is this an option for you? Commented Jul 8, 2015 at 22:43

1 Answer 1

3

You should pass to $urlparams an array where the keys are variable names and values are the corresponding filters of this variables. For example:

$urlparams = array(
    'catid' => 'INT',
    'id' => 'INT',
    'cid' => 'ARRAY',
    'year' => 'INT',
    'month' => 'INT',
    'limit' => 'UINT',
    'limitstart' => 'UINT',
    'showall' => 'INT',
    'return' => 'BASE64',
    'filter' => 'STRING',
    'filter_order' => 'CMD',
    'filter_order_Dir' => 'CMD',
    'filter-search' => 'STRING',
    'print' => 'BOOLEAN',
    'lang' => 'CMD',
    'Itemid' => 'INT'
);

This array is used to build the cache in the parent controller's display() method:

/libraries/legacy/controller/legacy.php

// Display the view
if ($cachable && $viewType != 'feed' && $conf->get('caching') >= 1)
{
    $option = $this->input->get('option');
    $cache = JFactory::getCache($option, 'view');

    if (is_array($urlparams))
    {
        $app = JFactory::getApplication();

        if (!empty($app->registeredurlparams))
        {
            $registeredurlparams = $app->registeredurlparams;
        }
        else
        {
            $registeredurlparams = new stdClass;
        }

        foreach ($urlparams as $key => $value)
        {
            // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}.
            $registeredurlparams->$key = $value;
        }

        $app->registeredurlparams = $registeredurlparams;
    }

    $cache->get($view, 'display');
}
else
{
    $view->display();
}

As you can see it is used for $app->registeredurlparams which is used in the JCache class to make the unique id of the cache in the makeId() method:

/libraries/joomla/cache/cache.php

/**
 * Create safe id for cached data from url parameters set by plugins and framework
 *
 * @return  string   md5 encoded cacheid
 *
 * @since   11.1
 */
public static function makeId()
{
    $app = JFactory::getApplication();

    $registeredurlparams = new stdClass;

    // Get url parameters set by plugins
    if (!empty($app->registeredurlparams))
    {
        $registeredurlparams = $app->registeredurlparams;
    }

    // Platform defaults
    $defaulturlparams = array(
        'format'    => 'WORD',
        'option'    => 'WORD',
        'view'      => 'WORD',
        'layout'    => 'WORD',
        'tpl'       => 'CMD',
        'id'        => 'INT'
    );

    // Use platform defaults if parameter doesn't already exist.
    foreach ($defaulturlparams as $param => $type)
    {
        if (!property_exists($registeredurlparams, $param))
        {
            $registeredurlparams->$param = $type;
        }
    }

    $safeuriaddon = new stdClass;

    foreach ($registeredurlparams as $key => $value)
    {
        $safeuriaddon->$key = $app->input->get($key, null, $value);
    }

    return md5(serialize($safeuriaddon));
}

This great article will explain more about Joomla cache.

1
  • Thanks for the detailed explanation! Seems I misunderstood how the urlparams worked. I had seen them used wrongly in a blog article and assumed that was the way to do it. I'll give it a go setting the variables from the state with JInput.
    – Adam B
    Commented Jul 19, 2015 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.