Free Result in MySQLi (OOP)

suntrop

Erfahrenes Mitglied
Hallo.
Ich finde einfach nicht heraus wie ich ein MySQLi-Objekt freigeben kann.
Ich erhalten nämlich folgende Meldung: Commands out of sync; you can't run this command now
Das tritt nach einem multi_query() mit zwei UPDATEs auf. Habe gelesen, dass hier mysqli_free_result die Lösung wäre.

Jetzt habe ich hunderte Schreibweisen getestet, aber keine funktioniert.

PHP:
$sql = '
UPDATE `users` SET
	`username` = ' . $db->quoteSmart($_POST['userUsername']) . ',
	`password` = md5(' . $db->quoteSmart($_POST['userUserpassword']) . '),
	`lastChange` = NOW()
WHERE
	id = ' . $db->quoteSmart($givenUserId) . ';';
$sql .= '
UPDATE `userdetails` SET
	`gender` = ' . $db->quoteSmart($_POST['userGender']) . ',
	`title` = ' . $db->quoteSmart($_POST['userTitle']) . ',
	`firstName` = ' . $db->quoteSmart($_POST['userFirstName']) . ',
	(…)
	`businessBranchId` = ' . $db->quoteSmart($_POST['userBranch']) . ',
	`mailFromAdmin` = ' . $db->quoteSmart($_POST['userAllowEmailsAdmin']) . ',
	`mailFromUser` = ' . $db->quoteSmart($_POST['userAllowEmails']) . '
	WHERE
	userId = ' . $db->quoteSmart($givenUserId);

PHP:
if ($db->multi_query( $sql )) {
  do {
	  if ($db->store_result()) {
		  echo 'test!<br>';
	  }
  } while ($db->store_result());
} else {echo 'test2<br>'; }

$db->freeRes($result);

Was muss ich den "befreien"? Mein DB-Objekt ($db)? Ein wirkliches $result gibt es doch bei den zwei UPDATES gar nicht?!
Der Fehler tritt immer bei der nachfolgenden SELECT-Abfrage auf. Z.B.:
PHP:
$sql = '
SELECT
	ud.id,
	ud.firstName AS Vorname,
	ud.lastName AS Nachname
FROM
	userdetails ud
LEFT JOIN (
	users u
	)
	ON (
		u.id = ud.userId
	)
WHERE
	u.id = ' . $user->getProperty('id');
	
$result = $db->sql($sql);
while ($row = $result->fetch_assoc()) {
	$theUser = $row;
}

Hier noch die Funktion freeRes() in der DB-Klasse:
PHP:
function freeRes($givenresult){
        $givenresult->free_result(); 
    }

Hat jemand einen Rat für mich?
 
Ein MySQLi Objekt gibst du frei, in dem du die Variable die das Objekt beinhaltet freigibst, z. B. mit [phpf]unset[/phpf].

Die Methode free_result() gehört allerdings nicht der MySQLi Klasse selbst an, sondern der Klasse mysqli_stmt.

Spontan finde ich deine Wrapperklasse nicht gerade angenehm. Warum nutzt du keine Prepared Statements? Gerade wegen diesen sollte man MySQLi nutzen.
Bei dir sieht es m. E. nach so aus, als würdest du dir eine MySQLi Wrapperklasse bauen und dann doch wieder genau so nutzen wie MySQLi selbst.
 
PreparedStatements sind nur bei Singel-Queries nicht bei Multi-Queries wie ich sie oft benötige zulässig. Sonst würde ich auch auf PS setzen. Oder irre ich mich hier?

Nun, leider bin ich jetzt nicht weiter als vorher. unset() wird dann wohl nicht das richtig hier sein. Die Seite zu free_result ist für mich nicht hilfreich. Keine Ahnung was dort steht :confused:
Ich habe jetzt eine neue Funktion in der DB-Klasse erstellt und dort
PHP:
parent::mysqli_stmt::free_result;
rein geschrieben. Das ist wohl nicht erlaubt :-) Wie komme ich aus meiner Wrapper-Klasse zur mysqli_stmt-Klasse?
Und ist es dann richtig, dass ich trotzdem mein DB-Objekt die Funktion aufrufen lasse? Bsp: $db->mache-frei();
 
mysqli::multi_query() liefert kein mysqli_stmt sondern bool zurück. Somit hast du recht, das du kein PS an dieser Stelle verwenden kannst. Ein multi_query-Aufruf schlägt fehl oder nicht. Die Daten bekommst du über den store_result()-Aufruf. Dieser liefert ein mysqli_result Objekt zurück, welches die Methode free() anbietet.

Das ist im Beispiel 1 auf dieser Seite gut erkennbar.
 
Die Daten bekommst du über den store_result()-Aufruf. Dieser liefert ein mysqli_result Objekt zurück, welches die Methode free() anbietet.
Das ist doch mal verständlich erklärt! Danke.

Das ist im Beispiel 1 auf dieser Seite gut erkennbar.
Dafür muss ich aber schon vieles davon wissen und verstehen, denn viel anders als mein Code sieht das auch nicht aus. Habe meine paar Zeilen jetzt wie folgt geändert, und damit funktioniert es auch!
PHP:
if ($db->multi_query($sql)) {
	do {
		/* store first result set */
		if ($result = $db->store_result()) {
			$result->free();
		}
		/* print divider */
		if ($db->more_results()) {
			
		}
	} while ($db->next_result());
}

Danke euch für die schnelle Hilfe!
Grüße
suntrop
 
Zurück