[RESOLU] serialize, unserialize et cache de requete mysql

Mammouth du PHP | 504 Messages

04 févr. 2014, 13:28

bonjour a tous,

j'ai un page php comme ceci:
require 'class/class.cache.php';
define('ROOT', dirname(__FILE__));
$Cache = new Cache(ROOT.'/tmp',60);

if(!$Cache->start('MonsuperCache')){
$page = mysql_fetch_array(mysql_query("SELECT id, name, description, longDescription, manufacturer, price, terms, shippinghandling, validFrom, validTo, smallImage, largeImage, currencyCode, extra1, mid_place, extra2, extra3, merchantCategory, deepLink, extra1, lat, lng
					FROM event_sale
					WHERE event_sale.id='".addslashes($_GET['id'])."'
					LIMIT 1"));						
}
$Cache->end();
et ma classe cache.class.php
class Cache{

public $dirname;
public $duration;
public $buffer;

public function __construct($dirname, $duration){
	$this->dirname = $dirname;
	$this->duration = $duration;	
}

public function write($filename, $content){
return file_put_contents($this->dirname.'/'.$filename, serialize($content));	
}	

public function read($filename){
$file = $this->dirname.'/'.$filename;
if(!file_exists($file)){
	return false;
}
$lifetime = (time - filemtime($file)) / 60;	
if ($lifetime > $this->duration){
	return false;
}	
return file_get_contents(unserialize($file));
}

public function delete($filename){
$file = $this->dirname.'/'.$filename;
if(file_exists($file)){
unlink($file);
}
}

public function clear(){
$files =glob($this->dirname.'/*');
foreach( $files as $file){
unlink($file);
}
}	
	
public function start($cachename){
if($content = $this->read($cachename)){
	echo unserialize($content);
	$this->buffer = false;
	return true;
	}		
ob_start();
$this->buffer = $cachename;	
}

public function end(){
	if(!$this->buffer){
		return false;
	}
$content = ob_get_clean();
echo $content;
$this->write($this->buffer, serialize($content));	
}		
		
}
Résultat dans mon fichier 'Monsupercache: s:7:"s:0:"";";

si dans ma page je remplace ma requete mysql par une variable comme $variable='ici tout va bien'; et je retire les serialize et unserialize cela fonctionne parfaitement parfaitement.

Merci de votre aide.

ViPHP
xTG
ViPHP | 7331 Messages

04 févr. 2014, 14:21

Il te manque un appel de fonction fondamental.
La fonction write. ;)
Actuellement tu ne stockes que ce qui est affiché, or aucun affichage n'est fait dans ton script.

Mammouth du PHP | 504 Messages

04 févr. 2014, 14:45

Ah, c'est pas faux; en fait, je me suis basé sur un tuto.

En fait, je cherche a stocké une fois pour toutes le résultat de mes requetes qui sont trés lourdes. le résultat est lui meme traité par la suite de diverses façons:
$city = explode(" | ", $page['extra2']);
$artiste = '';
foreach($a_break AS $variable => $valeur) {
$a_break1 = explode("|", $valeur);
$artiste.= @$a_break1[1].' '.@$a_break1[2].', ';
}
$content['artiste'] = $artiste;
etc.. etc...

Comment faire alors ?

Mammouth du PHP | 504 Messages

04 févr. 2014, 15:31

Je ne peux pas faire ça:
if(!$Cache->start('MonsuperCache')){
$page = mysql_fetch_array(mysql_query("SELECT id, name, description, longDescription, manufacturer, price, terms, shippinghandling, validFrom, validTo, smallImage, largeImage, currencyCode, extra1, mid_place, extra2, extra3, merchantCategory, deepLink, extra1, lat, lng
					FROM event_sale
					WHERE event_sale.id='".addslashes($_GET['id'])."'
					LIMIT 1"));	
echo $page;									
}
$Cache->end($page);	
en plus ça va me donner un Array.

Je vois ce que tu veux dire mais je ne trouve pas la solution.

Mammouth du PHP | 504 Messages

04 févr. 2014, 16:05

En fait mon soucis vient d'ici:
public function end(){
        if(!$this->buffer){
                return false;
        }
$content = ob_get_clean();
echo $content;
$this->write($this->buffer, serialize($content));       
}
ob_get_clean() me donne la valeur de mon contenu, or je n'ai pas de echo donc rien n'a été mis en tampon.

il faut que je mette autre chose ou que je lui donne une valeur.

Mammouth du PHP | 571 Messages

04 févr. 2014, 17:33

je ne suis pas sûr que ta classe fonctionne, par exemple à la place de la fonction time() il y a time :
 $lifetime = (time - filemtime($file)) / 60;     // 
ta classe ne gère non plus les accès concurrents c-ad-d si un internaute écrit dans le fichier de cache et en même un autre est en train de lire ça risque de corrompre le fichier de cache car il n y a aucun verrou qui a été mis pour l'accès au fichier de cache pendant la réécriture.
c'est mieux d'utiliser des solutions de cache déjà fonctionnelles comme memcache.(integré à php) ou phpFastCache qui utilise memcache , un fichier plat.

le principe de ce que tu souhaites faire, c'est de vérifier (avant toute requête sql) que le cache est à jour(ou existe) .dans ce cas tu affiches directement les données provenant du cache.si le cache n'existe pas(ou n'est pas à jour) tu extrais alors des données de la BD pour les stocker dans un array lequel sera mis en cache .rapidement ça ressemble ceci:
//cas de Memcache
$mysqli =new mysqli(---------);
$mem = new Memcache;

/* connexion au serveur de cache */
$mem->connect('localhost', 11211);

$data = array();
$data = $mem->get('super-cache');
if ($data === false ){ //le cache est vide
$sql ="SELECT * FROM laTable";
 if( $res = $mysqli->query($sql ) ){
   while( $row =  $res->fetch_assoc() ) {

     $data[] = $row;
  }
$mem->set('super-cache', serialize($data), MEMCACHE_COMPRESSED, 1800);//durée du cache 1800s
 }//if
}else{ //le cache contient des données, on alors afficher
var_dump(unserialise($data) );
}

Mammouth du PHP | 504 Messages

04 févr. 2014, 18:34

Merci yann.

je regarde ça. La classe fonctionne trés bien. il faut juste que je l'adapte comme le cite XTG.

De plus, je suis encore sous mysql, il faut que je voit le code que tu m'as donné et le mettre en mysql.

Mammouth du PHP | 504 Messages

04 févr. 2014, 19:04

Je vais me tourner vers phpfastcache. ça m'a l'air parfait pour ce que je veux faire :)

Mammouth du PHP | 571 Messages

05 févr. 2014, 01:48

normalement si la requête sql marche bien la mise en cache ne devrait pas poser problème:
<?php

require_once("../phpfastcache/phpfastcache.php");
phpFastCache::setup("storage","auto");

$cache = phpFastCache();
$content = array();

$content = $cache->get("product_page");


if( $content == null) { //le cache est vide, on le charge à partir des données provenant  de la bd
  echo "mise en cache en cours...";
  $result = mysql_query("SELECT id, name, description, longDescription, manufacturer, price, terms, shippinghandling, validFrom, validTo, smallImage, largeImage, currencyCode, extra1, mid_place, extra2, extra3, merchantCategory, deepLink, extra1, lat, lng
FROM event_sale
WHERE event_sale.id='".addslashes($_GET['id'])."'
LIMIT 1");

  while ( $row = mysql_fetch_array( $result ) ) {
   $content[] = $row;
   }
  $cache->set("product_page", serialize($content ) , 3600); //mise en cache du tableau de données($contents) pour une durée d'1 heure
 
} else { // le cache contient des données, on les recupère du cache pour les afficher
 echo "Cache déjà chargé!!!!";
  var_dump(unserialize($content ));
  //on parcours avec une boucle le tableau unserialize($content ) pour afficher les données
     }



  ?>   

Mammouth du PHP | 504 Messages

05 févr. 2014, 12:21

Merci yann.

Je vais avancer avec ça :)