2009-12-19 10 views
4

J'ai créé une classe MySQLi simple pour un projet sur lequel je travaille afin de la rendre plus facile et plus simple à tirer et à pousser vers la base de données. (également pour se familiariser avec OOP en PHP)PHP comment vérifier si une requête MySQLi doit être fermée?

Un problème que je continue à courir est dans un effort pour le rendre aussi efficace que possible. J'essaie de fermer/libérer chaque requête/instruction/ensemble de résultats. Ce faisant, je reçois l'erreur suivante beaucoup:

Warning: mysqli_result::close(): Couldn't fetch mysqli_result 

Je pense que je reçois ce qui précède précisément parce qu'il essaie de fermer la requête deux fois de suite.

Actuellement, ma classe peut faire des déclarations préparées et non préparées. J'essaie donc de fermer les requêtes/instructions à 2 endroits. Je vérifie lors de la préparation d'une déclaration si j'ai déjà préparé une déclaration, si c'est le cas, je dois fermer l'ancien avant d'en faire un nouveau et enfin dans le destructeur de la classe.

Je me rends compte que je pourrais juste fermer la requête/déclaration après avoir tiré et stocké le résultat, mais cela semble être en désordre pour quelques raisons. Pour un, il supprime la possibilité de réutiliser l'instruction préparée. En plus de m'interdire de tirer quelques informations sur la requête après qu'elle a été exécutée, comme les lignes affectées et autres. Je sais que je pourrais simplement stocker cette information pour chaque requête et ce non, mais il semble que la bonne façon de résoudre ce problème serait de fermer/libérer la requête/instruction si je dois en faire une autre, et encore à la fin du script.

J'ai essayé de jeter un coup d'œil sur la façon dont je devrais gérer correctement cette tâche, mais j'ai été incapable de trouver quoi que ce soit. Donc, ma question est, est-il de toute façon de tester si une requête ou une déclaration doit être fermée ou libérée? Ou y a-t-il une meilleure façon de tenter de résoudre ce problème?

Merci pour toute aide ou information que tout le monde peut vous offrir.

Répondre

1

Je pense que s'il n'y a plus de lignes dans le jeu de résultats, il devrait être fermé automatiquement. Donc, si vous parcourez l'ensemble des résultats, il n'est pas nécessaire d'appeler mysqli_result. Toutefois, vous devez le fermer si vous ne récupérez, disons, que la première ligne d'un jeu de résultats contenant environ 100 lignes.

+0

Hrm cela semble être un peu vrai. Je jouais avec un code de test faisant un 'var_dump' après l'exécution et l'autre après la récupération. Ils impriment la même chose. Lorsque vous faites un 'var_dump' après une fermeture bien que vous obteniez' L'accès à la propriété n'est pas encore autorisé ', il est évident que vous faites quelque chose de différent. Bien que, si c'est différent, l'efficacité est la question? De même, lorsque je limite une requête à 1 ligne (par exemple 'LIMIT 0, 1'), l'appel de $ stmt-> fetch() lui-même ne ferme pas l'instruction. Mais si je fais une boucle while et echo pour confirmer qu'il n'y a qu'une seule ligne, elle la ferme. Des idées? – anomareh

0

Vous pouvez le définir sur null après l'avoir fermé, et vérifier null dans le destructeur avant de le fermer là.

De toute évidence, vous souhaitez uniquement annuler une instruction préparée lorsque vous êtes sûr d'avoir fini de l'utiliser.

+0

Est-ce la même chose que de fermer une déclaration? Je n'ai vraiment aucun problème à laisser les choses être comme ça. Je ne veux pas m'assurer que c'est fermé sans raison. J'avais juste l'impression que fermer une déclaration et libérer des ensembles de résultats était la bonne façon de gérer les choses avec efficacité. Je sais que pour les petites choses, ce n'est probablement pas la plus grosse affaire, même si cela est important si votre projet voit beaucoup de trafic et se développe. Si vous travailliez dans de telles conditions, y avait-il une question d'efficacité, quelle serait la bonne chose à faire? – anomareh

0

Vous pouvez utiliser RAII ou un comptage de classe + référence usine pour gérer les instructions. De cette façon, vous n'avez pas besoin de vérifier explicitement quand il est temps de fermer quoi que ce soit. Sans voir les détails de la façon dont vous utilisez votre emballage, il est difficile d'entrer dans les détails. Le modèle accesseur de Objective-C peut également être utile, ce qui ressemblerait à quelque chose comme:

private function unsetStatement() { 
    if (isset($this->_stmt)) { 
     $this->_stmt->close(); 
     unset($this->_stmt); 
    } 
} 
function getStatement() { 
    return $this->_stmt; 
} 
function setStatement($stmt) { 
    $this->unsetStatement(); 
    $this->_stmt = $stmt; 
} 

Vous souhaitez ne jamais accéder au champ membre de l'instruction par les fonctions ci-dessus, même au sein de la classe. En fait, il ressemble plus à:

-(Statement *)statement { 
    return stmt_; 
} 
-(void)setStatement:(Statement *)stmt { 
    [stmt_ release]; 
    stmt = [stmt retain]; 
} 
0

C'est ce que j'utilise.S'il y a des résultats dans la déclaration, je sais que je dois libérer le résultat:

if($stmt->num_rows() != 0) 
{ 
    $stmt->free_result(); 

    return FALSE; 
} 
0

Si le résultat de la requête mysqli est déjà null, vous obtiendrez l'avertissement suivant en PHP 5:

Warning: myfunction(): Property access is not allowed yet in .... 

en principe, on pouvait traiter ces cas avec un gestionnaire d'erreur personnalisé ou simplement supprimer les avertissements/erreurs c.-à-is_object($mysqliqresult) && @$mysqliqresult->free()

Vous pouvez également utiliser mysqli- statements via la méthode prepare, en cours d'exécution plutôt que d'une mysqlidblink-> requête directement, comme suit:

$query = "SELECT heptagon,hexagon FROM pentagon ORDER BY hexagon"; 
$stmt = $dblink->prepare($query); 
$stmt->execute(); 
!$stmt->field_count() && $stmt->free_result(); 

suggestion de Justin est bien aussi.

Questions connexes