2010-10-28 8 views
0

J'ai essayé d'enregistrer des données de session PHP dans une base de données MySQL, mais je n'arrive pas à le faire fonctionner.session_set_save_handler - Pourquoi ce code ne fonctionne-t-il pas?

Pour un exemple simple, voici un code qui devrait incrémenter un compteur à chaque visite. J'ai vu d'autres exemples, etc. mais quelqu'un peut-il me dire pourquoi ce code ne fonctionne pas? (Apache/2.2.11 (Win32) DAV/2 mod_ssl/2.2.11 OpenSSL/0.9.8i PHP/MySQL 5.2.9 version client: 5.0.51a)

Voici la table de base de données MySQL:

CREATE TABLE IF NOT EXISTS `sessions` (
    `session_ID` varchar(32) COLLATE utf8_unicode_ci NOT NULL, 
    `session_data` mediumblob NOT NULL, 
    `access` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`session_ID`), 
    KEY `access` (`access`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Et le code PHP (il suffit de brancher vos informations d'identification db):

<?PHP 

function mysession_open() 
{ 

    global $sdbc; // Session Database Connection 

    if ($sdbc) { 
     return true; 
    } else { 
     return false; 
    } 

} 

function mysession_close() 
{ 

    global $sdbc; 

    return mysqli_close($sdbc); 

} 

function mysession_read($session_id) 
{ 
    global $sdbc; 

    $session_id = mysqli_real_escape_string($sdbc, $session_id); 

    $sql_sel = "SELECT session_data FROM sessions WHERE session_id = '$session_id'"; 
    $data_sel = mysqli_query($sdbc, $sql_sel); 
    $row_sel  = mysqli_fetch_array($data_sel); 

    if (isset($row_sel['session_data'])) { 
     return $row_sel['session_data']; 
    } else { 
     return ''; 
    } 

} 

function mysession_write($session_id, $session_data) 
{ 
    global $sdbc; 

    $access = time(); 

    $session_id = mysqli_real_escape_string($sdbc, $session_id); 
    $access  = mysqli_real_escape_string($sdbc, $access); 
    $session_data = mysqli_real_escape_string($sdbc, $session_data); 

    $sql_write = "REPLACE INTO sessions (session_ID, session_data, access) " . 
        "VALUES ('$session_id', '$session_data', '$access')"; 

    return mysqli_query($sdbc, $sql_write); 

} 

function mysession_destroy($session_id) 
{ 
    global $sdbc; 

    $session_id = mysqli_real_escape_string($sdbc, $session_id); 

    return mysqli_query($sdbc, $sql_del); 
} 


function mysession_gc($max) 
{ 
    global $sdbc; 

    $old = time() - $max; 
    $old = mysqli_real_escape_string($sdbc, $old); 

    $sql_old = "DELETE FROM sessions WHERE access < '$old'"; 

    return mysqli_query($sdbc, $sql_old); 

} 

global $sdbc; 
$sdbc = mysqli_connect('localhost', '...', '...', '...') or die('Could not connect to SDBC'); 

session_set_save_handler('mysession_open','mysession_close','mysession_read','mysession_write','mysession_destroy','mysession_gc'); 
session_start(); 

if (isset($_SESSION['counter'])) { 
    echo "counter is already set and it is " . $_SESSION['counter'] . '<br />'; 
    $_SESSION['counter']++; 
} else { 
    echo "counter is not set. setting to 1<br />"; 
    $_SESSION['counter'] = 1; 
} 

echo "<br />Dumping SESSION data:<br />"; 
var_dump($_SESSION); 

session_write_close(); 

?> 

Merci d'avance pour votre aide.

Si vous mettez en commentaire la ligne de code session_set_save_handler, cela fonctionne correctement (il s'incrémente). Mais en utilisant le gestionnaire de sauvegarde, ce n'est pas le cas.

+1

Qu'est-ce qui ne fonctionne pas? –

+0

En utilisant le gestionnaire de sauvegarde, il n'incrémente pas. Je pense que l'erreur se produit lorsque la fonction essaie d'écrire dans la base de données ('REPLACE ...') car mysqli_query retournera false à partir d'un handle d'objet db valide, mais PHP n'enverra pas cette information de débogage à la console. – TMG

Répondre

2

Aucun de vos appels de requête n'a de vérification d'erreur. Au lieu d'assumer aveuglément la partie de base de données fonctionne, faire une erreur de base de vérification à chaque étape, par exemple:

function mysession_write($session_id, $session_data) { 
    global $sdbc; 

    [...snip...] 

    $stmt = mysqli_query($sdbc, $sql_write); 
    if ($stmt === FALSE) { 
     error_log("Failed to write session $session_id: " . mysqli_error($sdbc); 
    } 
    return($stmt); 
} 

Il n'y a qu'une façon voie à une requête pour réussir, mais des millions de façons d'échouer.

+0

Merci; Je l'ai compris. L'utilisateur DB n'a pas l'autorisation DELETE. En fait, j'ai eu toutes sortes de code de débogage mais vous ne pouvez pas utiliser error_log (ou quoi que ce soit d'autre) comme vous l'avez parce qu'il ne va pas à la sortie standard: (par php.net: "Le gestionnaire" write "n'est pas exécuté Ainsi, la sortie des instructions de débogage dans le gestionnaire "write" ne sera jamais visible dans le navigateur ... écrivez dans un fichier à la place. ") Cela fonctionne donc: if (! $ result) { \t \t error_log ("Echec de l'écriture de la session $ session_id:". Mysqli_error ($ sdbc). "\ N", 3, 'errors.txt'); } – TMG

+0

J'ai généralement mes installations php configurées pour écrire son propre journal d'erreurs (paramètre error_log' ini) et garder une fenêtre ouverte avec 'tail -f' sur le fichier journal pendant le débogage. –

0

De the manual:
« Avertissement PHP 5.0.5 l'écriture et les gestionnaires proches sont appelés après la destruction de l'objet et ne peut donc pas utiliser des objets ou lancer des exceptions Les Destructeurs d'objet peuvent cependant utiliser les sessions

Il.. est possible d'appeler session_write_close() du destructeur pour résoudre ce problème de poule et d'oeuf. "

+0

S'il vous plaît prêter attention à la date de la question d'origine. Cette question a été répondue il y a près d'un an avec une réponse acceptée. –

Questions connexes