gnarf: 2 mySqli Verbinungen in PHP

Hallo !

ich bin ratlos. ich baue ein seit langem laufendes PHP-System endlich von mySql auf mySqli.

Dazu benutze ich eine selbst erstellte Klasse. Diese speichert die DB Verbindung, sowie query results als Objektvariablen.

Die betroffenen Methoden sind query und data. Query gibt ein eventuell existierendes Queryresult vorher mit $this->resid->free(); frei und führt dann die query durch.

Data ist im wesentlichen ein fesch_array. Wo von der aktuellen Quert also die nächste Zeile zurückgegeben wird.

Nun verwende ich 2 verschiedene Objekte $db und $db2, was nie ein Problem war.

$dbi->query("SELECT \* FROM ....  
  
while ($item = $dbi->data())  

{
             ...........

	$dbi2->query('UPDATE ....;');  

...........
} // end while

Nun wird mir aber durch die query mit der $dbi2 das aktuelle result der $dbi gelöscht !?!?!

Wie kann das sein. Ich komm einfach nicht drauf !!

DANKE !!!

  1. Hello,

    ich bin ratlos. ich baue ein seit langem laufendes PHP-System endlich von mySql auf mySqli.

    Dazu benutze ich eine selbst erstellte Klasse. Diese speichert die DB Verbindung, sowie query results als Objektvariablen.

    Die Klasse speichert gar nix. Die bechreibt nur, was später passieren soll.
    Wenn, dann wird die Speicherung von Daten von einer Instanz der Klasse gespeichert.
    Die Instanz muss dazu erstmal gebildet werden. Wenn Du mehrere Verbindungen zulassen willst, solltest Du auch mehrere Instanzen der Datenbankklasse zulassen, also KEIN Singleton dafür aufbauen.

    Mitzählen lassen, wieviele Connections schon bestehen, kannst du natürlich trotzdem. Dadurch könntest Du die Anzahl der Verbindungen für "einfache Benutzer" beschränken, während authorisierte Benutzer (Admin, System) immer noch Verbindungen erhalten.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://restaurant-zur-kleinen-kapelle.de
    1. Hi !

      ja richtig ich speichere also die DB-Verbindung etc. in 2 verschiedenen Objekten dieser Klasse. Ich verwende kein Singleton, keine static Variablen oder was auch immer. Mitzählen etc. ist nicht nötig.

      Ich verstehe nur einfach nicht warum mir ein

      $dbi2->result->free();

      das Query Ergebnis von $dbi löscht !

      Danke !

      Hello,

      ich bin ratlos. ich baue ein seit langem laufendes PHP-System endlich von mySql auf mySqli.

      Dazu benutze ich eine selbst erstellte Klasse. Diese speichert die DB Verbindung, sowie query results als Objektvariablen.

      Die Klasse speichert gar nix. Die bechreibt nur, was später passieren soll.
      Wenn, dann wird die Speicherung von Daten von einer Instanz der Klasse gespeichert.
      Die Instanz muss dazu erstmal gebildet werden. Wenn Du mehrere Verbindungen zulassen willst, solltest Du auch mehrere Instanzen der Datenbankklasse zulassen, also KEIN Singleton dafür aufbauen.

      Mitzählen lassen, wieviele Connections schon bestehen, kannst du natürlich trotzdem. Dadurch könntest Du die Anzahl der Verbindungen für "einfache Benutzer" beschränken, während authorisierte Benutzer (Admin, System) immer noch Verbindungen erhalten.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      1. Hoppla, jetzt bin ich draufgekommen, dass das Problem wo anders liegt.

        Ich ändere mit $dbi2 die selbe Tabelle (UPDATE) die ich mit $dbi abfrage, dadurch geht anscheinend das Ergebnis verloren. Mache ich die Query auf einer anderen Tabelle läuft es. Das ist aber unter mysql nicht so oder ?? Hätte ich noch nie gehabt, das Problem.

        1. Hello,

          Hoppla, jetzt bin ich draufgekommen, dass das Problem wo anders liegt.

          Ich ändere mit $dbi2 die selbe Tabelle (UPDATE) die ich mit $dbi abfrage, dadurch geht anscheinend das Ergebnis verloren. Mache ich die Query auf einer anderen Tabelle läuft es. Das ist aber unter mysql nicht so oder ?? Hätte ich noch nie gehabt, das Problem.

          Nach meinem Verständnis darf das nicht sein. Zwei Connections sollten aus Sicht der Datenbank zwei vollkommen unterschiedliche Benutzer repräsentieren.

          Darum habe ich ich Dich aber vorhin auch gefragt, ob Du den Connection-Identifier auch überall explizit und richtig angibst.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://restaurant-zur-kleinen-kapelle.de
      2. Hello,

        ja richtig ich speichere also die DB-Verbindung etc. in 2 verschiedenen Objekten dieser Klasse. Ich verwende kein Singleton, keine static Variablen oder was auch immer. Mitzählen etc. ist nicht nötig.

        Ich verstehe nur einfach nicht warum mir ein

        $dbi2->result->free();

        das Query Ergebnis von $dbi löscht !

        Um Dir da helfen zu können, müssten wir in die Klassendefinition hineigucken und die Funktionen und Methoden schrittweise überprüfen.

        Hast Du sichergestellt, dass immer eine Connection-Info angegeben wird in allen Methoden? Wenn Du die nämlichn weglässt, nimmt PHP die erste verfügbare aus seinem internen Stapel, bzw. die letzte benutze, was wohl so ungefähr das Gleiche sein sollte.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://restaurant-zur-kleinen-kapelle.de
        1. Hallo Tom,

          das ist sicher ein guter Ansatz, scheinst aber leider auch nicht zu sein. Also kopiere ich mal etwas Code zusammen: (wohl gemerkt sind das Auszüge !!!)

          class mysqli_db {

          var $link = false;  // link zur DB Verbindung wird im Konstruktor erzeugt
                  var $resid = false; // link sum result der Query. Wird in query() gesetzt.

          function __construct() {
             $this->link = new mysqli($this->host, $this->user, $this->passwd, $this->tables);
          }

          function query($sql)
          {
            if ($this->resid) @$this->resid->free();

          $this->resid = $this->link->query($sql);
            if (!$this->resid)  {$this->echoerror(); return false;}
            return $this->resid;
          }

          function data()
          {
            if (!is_object($this->resid))
            {
              if ($this->doerror)
                echo ("<b>Keine Abfrage!</b><br>");
              return false;
            }
            $result = $this->resid->fetch_assoc();
            return $result;
          }

          }

          der eigentliche code :

          $dbi->query("SELECT \* FROM beitraege WHERE 1 LIMIT 3;");  
          while ($item = $dbi->data())  
          

          {

          	$dbi2->query('  
          		UPDATE beitraege SET myversion ="'.htmlentities($new).'"  
          		WHERE id = "'.$item['id'].'";');  
          	  
          	  
          	echo ($item['id'].'<>');  
          } // end while  
          

          Wenn ich das Skript laufen lasse wird die While Schleife nur einmal betreten.
          Nehme ich die $dbi2->query raus, dann läuft sie wie erwartet 3x durch.

          Ändere ich die dbi2 query auf ein UPDATE einer anderen Tabelle wird nur 1x durchlaufen.
          Mache ich eine SELECT query wird 3x durchlaufen.

          Es war also nicht richtig, dass die Tabelle eine Rolle spielt, sondern ob ein UPDATE oder ein SELECT gemacht wird. UPDATE löscht mir das Ergebnis, SELECT nicht.

          Sehr lustig ;-)

          1. Jetzt hab ich ihn !!!

            In der Methode query war vorher

            if ($this->resid) @$this->resid->free_result();

            Das war bei mySql gut, nicht aber bei mySqli.

            if (is_object($this->resid)) @$this->resid->free_result();

            und es läuft !

            Anscheint war in $dbi2->resid irgendein Wert (nach der UPDATE query) gespeichert, wodurch der if-zweig betreten wurde. Dieser Wert war aber anscheinend nicht geeignet um das Suchergebnis mit free freizugeben, wodurch irgendwie das letzte verwendete MySqli Suchergebnis freigegeben wurde. Dieses war das vom anderen Objekt. Zumindest ist das meine einzige Erklärung.

            Mit is_object läuft es einwandfrei! Bei mySql war die einfach if Abfrage ausreichend, bei mySqli nicht.

            Danke, Tom für die Hilfe. Du hast mich auf die richtige Fähre gebracht.

            Das war jetzt schon eine harte Nuss.

            1. Tach!

              Jetzt hab ich ihn !!!

              Mein Gefühl sagt mir, dass du etwas gefunden hast, das den Fehler vermeidet, aber nicht die wahre Ursache erkannt hast. Mir fällt sie aber auch grad nicht auf. Ich müsste das erstmal nachstellen, um zu sehen, ob das reproduzierbar ist, aber .. jetzt nicht.

              if (is_object($this->resid)) @$this->resid->free_result();

              Es darf nicht nur irgendein Objekt sein, sondern eins der Klasse mysqli_result. Prüf das lieber mit instanceof. Du solltest auch nciht die Fehlerausgabe unterdrücken, denn zu dieser Funktion ist nicht beschrieben, dass sie Fehler liefert. Du hättest ohne @ schon eher erkennen können, dass $this->resid->free() nicht aufgerufen werden konnte, wenn $this->resid gar kein Objekt mit der Methode free() ist.

              Anscheint war in $dbi2->resid irgendein Wert (nach der UPDATE query) gespeichert,

              Sowas lässt sich wenigstens mit einem var_dump() ergründen. Zudem steht es im PHP-Handbuch, was in welchem Fall zurückgegeben wird.

              Grundsätzlich stellt sich mir die Frage, warum du einen Wrapper baust, statt die vorhandenen Klassen zu erweitern. Das ist muss nicht unsinnig sein, aber eine gute Begründung solltest du dafür zumindest haben. Die musst du mir auch nicht unbedingt sagen, aber zumindest für dich solltest du die mal ausformuliert haben (und dazu darüber nachgedacht haben).

              Weiterhin: Warum gibt query() eine Result-ID zurück, wenn du doch eigentlich gedenkst, die Daten über data() zurückzugeben? Die braucht doch außerhalb des Objektes keiner. Je mehr der anwendende Code von den Interna des MySQL-Handling wissen muss, desto fragwürdiger wird der Einsatz deines Wrappers, und desto erwägenswerter wird es, lediglich die vorhandenen Klassen um die von dir vermisste Funktionalität zu erweitern.

              dedlfix.

          2. Hello,

            ?

            var $resid = false; // link sum result der Query. Wird in query() gesetzt.

            Ich weiß nicht, was Du unter ::resid alles definiert hast.

            if ($this->resid) @$this->resid->free();

            $this->resid = $this->link->query($sql);
              if (!$this->resid)  {$this->echoerror(); return false;}
              return $this->resid;

            Deshalb hätte ich erstmal hier angefangen:

            http://www.php.net/manual/en/mysqli-result.free.php

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://restaurant-zur-kleinen-kapelle.de
        2. Tach!

          Hast Du sichergestellt, dass immer eine Connection-Info angegeben wird in allen Methoden? Wenn Du die nämlichn weglässt, nimmt PHP die erste verfügbare aus seinem internen Stapel, bzw. die letzte benutze, was wohl so ungefähr das Gleiche sein sollte.

          Das war nur bei den mysql_*-Funktionen so. Die mysqli_*-Funktionen verlangen immer die Connection-Ressource - und zwar als ersten Parameter. Unter mysql_* war das meist der letzte Parameter und der war dann optional. Mit der objektorientierten Variante verliert sich dieses Problem sowieso, weil man da ja explizit das Objekt angeben muss, welches die individuelle Connection-Ressource mit sich rumschleppt.

          dedlfix.

          1. Hello,

            Hast Du sichergestellt, dass immer eine Connection-Info angegeben wird in allen Methoden? Wenn Du die nämlichn weglässt, nimmt PHP die erste verfügbare aus seinem internen Stapel, bzw. die letzte benutze, was wohl so ungefähr das Gleiche sein sollte.

            Das war nur bei den mysql_*-Funktionen so. Die mysqli_*-Funktionen verlangen immer die Connection-Ressource - und zwar als ersten Parameter. Unter mysql_* war das meist der letzte Parameter und der war dann optional. Mit der objektorientierten Variante verliert sich dieses Problem sowieso, weil man da ja explizit das Objekt angeben muss, welches die individuelle Connection-Ressource mit sich rumschleppt.

            Gibt es nicht für manche Methoden auch noch prozedurale Schwestern, die man am Objekt vorbei nutzen kann? Oder habe ich mich da jetzt geirrt?

            Ist ja sinnvoll, wenn eine Nutzung ohne Link-Identifier nicht mehr funktioniert... Aber wie war das mit den Pferden?

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://restaurant-zur-kleinen-kapelle.de
            1. Tach!

              Die mysqli_*-Funktionen verlangen immer die Connection-Ressource - und zwar als ersten Parameter. [...] Mit der objektorientierten Variante verliert sich dieses Problem sowieso, weil man da ja explizit das Objekt angeben muss, welches die individuelle Connection-Ressource mit sich rumschleppt.
              Gibt es nicht für manche Methoden auch noch prozedurale Schwestern, die man am Objekt vorbei nutzen kann? Oder habe ich mich da jetzt geirrt?

              Ja, gibt es. Aber bei denen ist nun, wie ich schrieb, die Angabe einer Link-Ressource zwingend notwendig.

              dedlfix.