2

i made this function: /* MEMCACHE */

function cache_query($sql,$nombre,$tiempo = -1){
    $cache = new Memcache();
    $cache->pconnect('localhost',11211);
    $query_cacheada = $cache->get($nombre);
    if ( $query_cacheada  === false ) {
             /* key not in memcache, perfom query, cache it and return */
         $res = mysql_query($sql);
         $cache->set($nombre,$res, 0, 60*60*24);  
         return $res; /* this looks good */
    }else{
             /* key in memcache, just return cached  */
         return $query_cacheada;  /* this doesnt return right elements */
    }
}

wich i am using so:

class text{

    protected $id;
    protected $key;
    protected $language;
    protected $text;

    function __construct($clave,$lan){
       $consulta = cache_query("SELECT * FROM textos  
                                WHERE clave = '$clave' AND lengua = '$lan'" ,"TRANSLATION_".$clave."_".$lan);


        if(mysql_num_rows($consulta)>0){
            while($item = mysql_fetch_array($consulta)){
                $this->id = $item['id'];
                $this->clave = $item['key'];
                $this->lengua = $item['language'];
                $this->texto = $item['text'];

            }
                return true;
         }
    }
    function get_text(){
          return $this->text;
    }
}
function translation($key,$language){
     $tem = new text($key,$language);
     return $tem->get_text();
}

then:

$translationText = translation('hello','fr');

The problem is that it stores in cache arrays (always zero), var_dump($m->get(k)) returns:

int(0) int(0) int(0) int(0) int(0) int(0) int(0) int(0) int(0) int(0) int(0) .....

And the $sql query is fine because the rows are collected fine and printed fine, the problem is with the stored value..

I have cleared the cache doing (several times, to make sure the values are not from a previous wrong output):

$consulta = $cache->get($nombre);
             /* manually*/
             $consulta = false;
        if ( $consulta === false) {
            $consulta = mysql_query($sql);
            $cache->set($nombre,$consulta, MEMCACHE_COMPRESSED, 60*60*24);
        };

so.. what am I missing?

EDIT

Here is a codepad, the problem is the mysql_query and memecache is not enabled, but in case someone wants to fiddle with it a bit

http://codepad.viper-7.com/PJNepH

5
  • Is it ok that you pass $sql but use $query, and pass $tiempo but use $iempo? Commented May 26, 2012 at 21:54
  • yep. You want to know what's actually in that variable, don't you? Commented May 26, 2012 at 22:07
  • hey! finnaly I got to see var_dump: boolean(false) so it's not finidng it. also edited the function a bit @zerkms Commented May 27, 2012 at 20:28
  • Why are you trying to use memcache at all, when the MySQL query cache should do a perfectly good job of this completely transparently to your application? Commented May 29, 2012 at 0:45
  • @eggyal too much mysql load.. i know it's not the right fix but it would buy me some time.. I would like to know how to do this anyway :) Commented May 29, 2012 at 6:56

3 Answers 3

3
+300

You can only cache something that can be serialized. This includes everything but the type resource (which is returned from a successful mysql_query). You need to change your logic a bit so that you are caching an array. Change this:

$res = mysql_query($sql);
$cache->set($nombre,$res, 0, 60*60*24); 

To:

$res = mysql_query($sql);
$rows = array();
while($row = mysql_fetch_array($res)) $rows[] = $row;
$cache->set($nombre, $rows, 0, 60*60*24); 

Then change this:

if(mysql_num_rows($consulta)>0){
    while($item = mysql_fetch_array($consulta)){
        $this->id = $item['id'];
        $this->clave = $item['key'];
        $this->lengua = $item['language'];
        $this->texto = $item['text'];

    }
    return true;
}

To:

foreach($consulta as $item){
       $this->id = $item['id'];
       $this->clave = $item['key'];
       $this->lengua = $item['language'];
       $this->texto = $item['text'];
}

// This is your old code written to work with a 2D array instead of a resource,
// But this keeps overwriting the same variables in a loop,
// if you selected multiple rows; otherwise you don't even need a loop and can just do:

$this->id = $consulta[0]['id'];
$this->clave = $consulta[0]['key'];
$this->lengua = $consulta[0]['language'];
$this->texto = $consulta[0]['text'];
Sign up to request clarification or add additional context in comments.

Comments

1

The important thing to note is that you cannot store a result resource returned from mysql_query. I would recommend looping through the result set, fetching them with mysql_fetch_array, and then storing those objects in the cache.

Edit As PaulP.R.O. pointed out, the explicit serialize/deserialize were redundant.

$result = mysql_query($sql) or die("Query failed");

$results = array();

while ($array = mysql_fetch_array($result))
{
    $results[] = $array;
}

$cache->set($nombre, $results, MEMCACHE_COMPRESSED, 60*60*24);

When retrieving from memcached, simply use the unserialized array.

$cachedItem = $cache->get($nombre);

if ($cachedItem !== false) {
    var_dump($cachedItem);
}

4 Comments

It's pointless to call serialize and unserialize, memcache will already do that automatically for objects or arrays.
hi! thanks for your answer but this while with mysq_fetch_object wont generate the same array than mysql_result so the values are not printed well and of corse not stored well... any idea why? (i am returning $results because $result has been emptyed in the loop)
@ToniMichelCaubet You can't store what is returned from mysql_query. You can only store what is returned from functions that use the result resource returned from mysql_query (e.g. mysql_fetch_object or mysql_fetch_array). @PaulP.R.O You're right. I'll remove the explicit serialize/deserialize functions.
Paul also rewrote some of your code, so it might be worth it to simply try his code changes out, if our reasons for not storing a result resource aren't clear.
0

Memcache doesn't accept TTLs longer than 30 days. You can also use a ttl of 0 to set the key to never expire OR you set a ttl of less than 30 days.

eliminating memcached's 30-day limit

To create an easily serializable variable, you can do something like this.

$consulta = mysql_query($sql);   
while ($row = mysql_fetch_assoc($consulta)) {
  $data[] = $row;
}
$cache->set($nombre,$data, MEMCACHE_COMPRESSED, 60*60*24);

6 Comments

Edited function, now it returns values! but for some reason, it stores the mysql result, and var_dump returns: int(0) int(0) int(0) int(0) int(0) int(0).... any idea? (before being cached they where displayed as expected, so the mysql query is fine)
Seems like it's serializing the mysql resource. Typically, what you'd want to do is format your data into a more easily serializable format, like a PHP array, or even JSON, then pass that to $cache->set.
I see your edit. this returns the same that cache wa s storing... don't you have to initialise $data? i think the problem is that my query returns an array of objects...
From a syntax standpoint, you actually don't have to initialize $data in this case. As this is just example code, I didn't deem it necessary. However, you should initialise it, as you will get a PHP notice in the $cache->set line if you do not. Have you cleared cache?
what i mean is that this mysql_query is something like 'select * from users where id=5'), so it doesnt contain an array of values but objects. is that ok the way i am doing it?
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.