0

Is there a way to cache virtual fields? I mean automatically, with the entity to which they belong, because I understand that, even if an entity is retrieved from the cache, virtual fields are generated whenever it is necessary.

Obviously I know I can take care of it personally, so (example):

protected function _getFullName()
{
    $fullName = Cache::read('full_name_for_' . $this->_properties['id'], 'users');

    if (empty($fullName)) {
        $fullName = $this->_properties['first_name'] . '  ' . $this->_properties['last_name'];

        Cache::write('full_name_for_' . $this->_properties['id'], $fullName, 'users');
    }

    return $fullName;
}

But I wanted to know if in fact CakePHP can do it directly.


EDIT

Context.

The Post entity has the text property. text can contain images (as html code), even remote. Now I have to store somewhere the url of the first image contained in the text and its size. So I have created the first_image virtual field, that uses a regex. The problem is rather with the image size: I can not do run every time the getimagesize() function, especially if the image is remote, for reasons that you can easily understand. So how to do?

Mirko Pagliai
  • 1,220
  • 1
  • 19
  • 36

2 Answers2

2

Is there a way to cache virtual fields?

No.

And what you do doesn't make much sense. The caching is for sure causing more overhead than that you gain anything from it in this case.

Use concat() on the DB level to concatenate the name instead.

Also if there would be a real need to cache a virtual property, then I would say there went something clearly wrong in the architecture.

floriank
  • 25,546
  • 9
  • 42
  • 66
  • Ok @burzum. The `Post` entity has the `text` property. `text` can contain images (as html code), even remote. Now I have to store *somewhere* the url of the first image contained in the `text` and its size. So I have created the `first_image` virtual field, that uses a regex. The problem is rather with the image size: I can not do run every time the `getimagesize()` function, especially if the image is remote, for reasons that you can easily understand. So how to do? – Mirko Pagliai Mar 24 '17 at 17:03
  • Simply do this kind of processing in the beforeSave() callback. Check the book.cakephp.org on how to use it. Extract the info there an store it. Next time you ask something it might be smart to come up with the actual problem instead of something else. ;) – floriank Mar 26 '17 at 11:50
0

It makes sense to me to want to prevent code in accessors/virtual fields from being executed more than once on the same request, which can easily happen if you use them several places in your script.

You can do a solution like this, but I'm not entirely sure how kosher it is:

private $fullName_cache = false;

protected function _getFullName()
{
if(!$this->fullName_cache){
    $fullName = Cache::read('full_name_for_' . $this->_properties['id'], 'users');

    if (empty($fullName)) {
        $fullName = $this->_properties['first_name'] . '  ' . $this->_properties['last_name'];

        Cache::write('full_name_for_' . $this->_properties['id'], $fullName, 'users');
    }

    $this->fullName_cache = $fullName;
}
return $this->fullName_cache;
}

I think there might be a nicer way to do this. There is mention of this sort of thing in the cookbook:

Code in your accessors is executed each time you reference the field. You can use a local variable to cache it if you are performing a resource-intensive operation in your accessor like this: $myEntityProp = $entity->my_property.

Anyone had luck implementing this?