1

I'm getting a big performance hit on front end requests (+15 seconds) when using a model to store / use data from one of my custom fieldtypes, cp requests for the same data appear unaffected.

The prepValue function:

public function prepValue($value)
{
    if( is_array($value) )
    {
        return FruitGrid_BlockModel::populateModels($value);
    }

    return $value;
}

And the model which is getting populated:

class FruitGrid_BlockModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'row' => array(AttributeType::Number),
            'col' => array(AttributeType::Number),
            'sizex' => array(AttributeType::Number),
            'sizey' => array(AttributeType::Number),
            'entryid' => array(AttributeType::Number),
            'rules' => array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        $string = '';
        if(is_array($this->rules))
        {
            foreach ($this->rules as $rule => $value)
            {
                switch ($rule)
                {
                    case 'fixedHeight':
                        $string .= ' height-'.$value;
                        break;
                    case 'desktopRuleOne':
                        $string .= ' desktop-'.$value;
                        break;
                    case 'tabletRuleOne':
                        $string .= ' tablet-'.$value;
                        break;
                    case 'mobileRuleOne':
                        $string .= ' mobile-'.$value;
                        break;
                }
            }
        }
        return trim($string);
    }

    public function getEntry()
    {
        $criteria = craft()->elements->getCriteria(ElementType::Entry);
        $criteria->id = $this->entryid;
        return $criteria->first();
    }
}

And pretty standard usage on the front end:

{% if entry.customFieldHandle|length %}

    {% for block in entry.customFieldHandle %}

        <h1>{{ block.entry.title }}</h2>
        <p>{{ block.entry.text }}</p>

        ...

    {% endfor %}

{% endif %}
0

1 Answer 1

2

Avoid calling block.entry multiple time per block since you only need to do that database query once. Alternatively you can use function memoization to cache the entry like this:

class FruitGrid_BlockModel extends BaseModel
{
    private $_entry;

    protected function defineAttributes()
    {
        return array(
            'row' => array(AttributeType::Number),
            'col' => array(AttributeType::Number),
            'sizex' => array(AttributeType::Number),
            'sizey' => array(AttributeType::Number),
            'entryid' => array(AttributeType::Number),
            'rules' => array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        //...
    }

    public function getEntry()
    {
        if(!$this->_entry){
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->id = $this->entryid;
            $this->_entry = $criteria->first();
        }

        return $this->_entry;

    }
}

This will only get the entry from the database once.

Also recommend renaming the rules attribute on the model to something like blockRules.

When you loop over the rules to create the ruleClasses string you may be looping over every rule created by the AttributeType declarations in your defineAttributes method.

4
  • Ah I see, removing {{ block.ruleClasses }} improved things a drop, but I was accessing {{ block.entry.customField }} loads of times, storing / caching the entry and accessing it via this var helped loads. So does it get the entry each time i hit block.entry?? Commented Sep 9, 2015 at 10:14
  • ah yes, you are doing a db call every time you do block.entry. You could cache it in the plugin function or just assign it once per block in the template like so: {% set blockEntry = block.entry %}. This would have been causing the huge slowdown more than my answer. Commented Sep 9, 2015 at 10:15
  • Yes, this was the issue, although your suggestion certainly helped speed things up. What do you mean by cache in the function? Set a var that is checked before grabbing the entry and set only if it has not be retrieved? Commented Sep 9, 2015 at 11:30
  • Sorry Luke, just saw you answer! Exactly as expected, thanks!!! Commented Sep 9, 2015 at 11:31

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.