CakePHP: Cannot read from a custom cache in 2.8.4? - cakephp

This is painfully simple, but I cannot determine why it simply will not work as the Cookbook suggests it will. I am getting a blank result when I run the following:
Cache::write('req_quals', $value, 'permacache');
Cache::read('req_quals', 'permacache');
The config looks like:
Cache::config('permacache', array('engine' => 'File', 'path' => CACHE . 'permacache' . DS, 'duration' => '+9999 days'));
The write works. I know this because I'm looking directly into the tmp/cache/permacache folder and I see the file with its contents inside.
I can write/read this value without any problem if I remove the 'permacache' from both lines.
Am I missing something obvious?

When Cake calculates duration, +9999 days returns a negative duration. You should avoid being a cool guy and just use +999 days as the documentation subtly suggests.

Related

CakePHP 3.4: how to cache virtual fields

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?
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.
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?

Can I use same param name multiple times in the URL for codeigniter-restserver?

http://example.com/api/transfer/transfers/code/456/code/234
When using $this->get('code') on a url like above I expect the REST library to return an array or a list of the codes.
Instead it returns the last one.
Is there a way to return both values in a list, or is there another recommandation for formating the URL.
Thank you
I know it has been long since you posted the question. However it could help other people looking for the same thing.
Assuming that transfer is your controller and transfers is the function, another way to format your url could be:
http://example.com/api/transfer/transfers?code[]=456&code[]=234
This was you perform $this->get('code') you'll get an array back.
If you are creating the url via code then you may use http_build_query(). It handles the necessary escaping. It means it will replace [ for %5B and ] for %5D, in this case.
The code would be like:
$codes = array(456, 234);
$query = http_build_query(array('code' => $data));
$url = 'http://example.com/api/transfer/transfers?' . $query;

CakePHP performance issues - cached view file size

On a CakePHP site (2.3.1) I have noticed the cached view file size is very large (10-60MB) per page.
Typically with sites I would expect the caching to just store pure HTML output but Cake is adding serialised PHP at the top of the files. From a performance perspective this large file size is problematic, using up gigabytes of space (we have 1000s of pages), and is not suited to APC caching (default max file size 1MB).
This is an example block at the top of the cached view file:
<!--cachetime:1363985272--><?php
App::uses('StaticController', 'Controller');
$request = unserialize(base64_decode('<removed>'));
$response = new CakeResponse();
$controller = new StaticController($request, $response);
$controller->plugin = $this->plugin = '';
$controller->helpers = $this->helpers = unserialize(base64_decode('<removed>'));
$controller->layout = $this->layout = 'default';
$controller->theme = $this->theme = '';
$controller->viewVars = unserialize(base64_decode('<removed>'));
Router::setRequestInfo($controller->request);
$this->request = $request;
$this->viewVars = $controller->viewVars;
$this->loadHelpers();
extract($this->viewVars, EXTR_SKIP);
?>
I'd prefer no PHP in there at all, as the HTML below is the static generated output. A massive overhead that accounts for all the file size.
Cache setting in bootstrap.php:
Cache::config('default', array('engine' => 'Apc'));
At present my only option is to improve the file size of the view cache files. Adding something like Varnish is not possible on this server as this point in time.
Any tips to resolve the file size issue would be great.
I was able to vastly reduce the size of cached view files in the end by making these two changes. Hopefully it is useful to anyone who runs into a similar issue.
1 - Model
There was a number of relationships between models, however I was only actually making using of the data on one side of the relation. For example, an article had images, but I also had a relation to get the article belonging to an image, which I never did. Making the relations 'one way' i.e. as required cut down on heavy queries.
2 - Controller
In my paginate array I had 'recursive'=>2, which was causing hundreds of extra queries per page. I was able to cut the queries on a heavy page down from 900 to 20 by changing this option to 'recursive'=>1. There was about 6 many to many relations on the model in question. This recursion level must have slipped in at some stage inadvertently.
I still feel it is odd for CakePHP to serialize PHP in the cached view files. A more optimal approach would be static HTML files without any PHP.

php cake inflection.php - why is "cookie" in list of uninflected words?

Simple question - in the CAKE php framework - in inflection.php (class inflection)
why is "cookie" in the list of terms NOT to apply pluralization to?
uninflected' => array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', 'people', 'cookie')
I get all of the rest but 'cookie' doesn't make sense. e.g. plural is cookies.
It is possible that it is in that list by mistake. The cookie/cookies part can also be found where it actually belongs: in the irregular words section.
But the inflection of this word works nevertheless.
You can pluralize and singulare Cookie/Cookies just fine (I confirmed it using the current 2.3 head).
I made a PR (you could have done the same, of course) to clear this up: https://github.com/cakephp/cakephp/pull/1048

how to force drupal function to not use DB cache?

i have a module and i am using node_load(array('nid' => arg(1)));
now the problem is that this function keep getting its data for node_load from DB cache.
how can i force this function to not use DB cache?
Example
my link is http://mydomain.com/node/344983
now:
$node=node_load(array('nid'=>arg(1)),null,true);
echo $node->nid . " -- " arg(1);
output
435632 -- 435632
which is a randomly node id (available on the system)
and everytime i ctrl+F5 my browser i get new nid!!
Thanks for your help
Where are you calling this? For example, are you using it as part of your template.php file, as part of a page, or as an external module?
Unless you have this wrapped in a function with its own namespace, try naming the variable differently than $node -- for example, name it $my_node. Depending on the context, the 'node' name is very likely to be accessed and modified by Drupal core and other modules.
If this is happening inside of a function, try the following and let me know what the output is:
$test_node_1 = node_load(344983); // Any hard-coded $nid that actually exists
echo $test_node_1->nid;
$test_node_2 = node_load(arg(1)); // Consider using hook_menu loaders instead of arg() in the future, but that's another discussion
echo $test_node_2->nid;
$test_node_3 = menu_get_object(); // Another method that is better than arg()
echo $test_node_3->nid;
Edit:
Since you're using hook_block, I think I see your problem -- the block itself is being cached, not the node.
Try setting BLOCK_NO_CACHE or BLOCK_CACHE_PER_PAGE in hook_block, per the documentation at http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_block/6
You should also try to avoid arg() whenever possible -- it's a little bit of a security risk, and there are better ways to accomplish just about anything arg() would do in a module environment.
Edit:*
Some sample code that shows what I'm referring to:
function foo_block ($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0] = array(
'info' => 'I am a block!',
'status' => 1,
'cache' => BLOCK_NO_CACHE // Add this line
);
return $block;
case 'view':
.....
}
}
node_load uses db_query, which uses mysql_query -- so there's no way to easily change the database's cache through that function.
But, node_load does use Drupal's static $nodes cache -- It's possible that this is your problem instead of the database's cache. You can have node_load clear that cache by calling node_load with $reset = TRUE (node_load($nid, NULL, TRUE).
Full documentation is on the node_load manual page at http://api.drupal.org/api/drupal/modules--node--node.module/function/node_load/6
I have had luck passing in the node id to node_load not in an array.
node_load(1);
According to Druapl's api this is acceptable and it looks like if you pass in an array as the first variable it's loaded as an array of conditions to match against in the database query.
The issue is not with arg(), your issue is that you have caching enabled for anonymous users.
You can switch off caching, or you can exclude your module's menu items from the cache with the cache exclude module.
edit: As you've now explained that this is a block, you can use BLOCK_NO_CACHE in hook_block to exclude your block from the block cache.

Resources