wofmoonheart: bind_param mit array möglich ?

Habe zwar bereits den Thread schon gefunden und wollte auch dort meine Frage reinsetzen, ging aber irgendwie nicht, weil ich den Antworte Button nicht fand, falls es überhaupt einen gibt.

Ich bin der Anleitung soweit gefolgt und komme einfach nicht mehr weiter:

Quelltext:

  
public function db_PS_select($stmt, $dataTyp=null, $sParams=null, $store=true)  
{  
		  
$values = array();  
$result = array();  
			  
			  
if ($dataTyp && $sParams)  
{  
  $stmt = $this->db_PS_execute($stmt, $dataTyp, $sParams);  
}  
			  
			  
if (!$meta = $stmt->result_metadata())  
{  
  // Fehlerbehandlung  
}  
			  
			  
while ($field = $meta->fetch_field())  
{  
  $values[$field->name] = null;  
}	  
			  
			  
foreach ($values as &$reference); //nix auszuführen  
		  
			  
if (!call_user_func_array(array($stmt, 'bind_result'), $values))  
{  
  // Fehlerbehandlung  
}  
			  
					  
  
  
// ACHTUNG:  
// ALLE FELDER BLEIBEN LEER, AUßER DAS LETZTE!!!  
// DAS LETZTE FELD ERHÄLT KORREKTEN WERT  
while ($stmt->fetch())  
{  
  $row = array();  
			  
				  
  foreach ($values as $key => $value)  
  {  
    echo $key . " : " . $value . "<br />";   // DEBUG  
    $row[$key] = $value;  
  }  
  
  echo "<br />";			  
  $result[] = $row;  
}  
  
return $result;  
			  
			  
  
// NUTZE ICH FOLGENDEN CODE ALTERNATIV, FUNKTIONIERT ES!  
/*  
$stmt->bind_result($rowThreadId, $rowThreadName, $rowKatId, $rowBenutzerId,  
  $rowThreadStatus, $rowThreadAntworten, $rowThreadGesehen, $row);  
  
$stmt->fetch();  
  
// ALLE WERTE VORHANDEN  
echo "$rowThreadId, $rowThreadName, $rowKatId, $rowBenutzerId, "  
  . "$rowThreadStatus, $rowThreadAntworten, $rowThreadGesehen, "  
  . "$row";  
*/  
  
}  
  

Setzte ich den alternativen Code ab, erhalte ich alle Felder. Mache ich es auf die erste Weise, ist nur das letzte Element mit dem Wert belegt.

Ausgabe, wenn der Code so läuft:

FORUM_POST_ID :
FORUM_POST_THREAD_ID :
FORUM_POST_BENUTZER_ID :
FORUM_POST_TITLE :
FORUM_POST_TIME :
FORUM_POST_TEXT :
FORUM_POST_IPADDR :
FORUM_POST_ORDER_ALT : 1084985379

FORUM_POST_ID :
FORUM_POST_THREAD_ID :
FORUM_POST_BENUTZER_ID :
FORUM_POST_TITLE :
FORUM_POST_TIME :
FORUM_POST_TEXT :
FORUM_POST_IPADDR :
FORUM_POST_ORDER_ALT : 1

  1. Hellihello

    Habe zwar bereits den Thread schon gefunden und wollte auch dort meine Frage reinsetzen, ging aber irgendwie nicht, weil ich den Antworte Button nicht fand, falls es überhaupt einen gibt.

    Welchen Thread?

    Ich bin der Anleitung soweit gefolgt und komme einfach nicht mehr weiter:

    Welche Anleitung?

    Das ist recht viel Code, wo genau liegt Dein Problem?

    Dank und Gruß,

    frankx

    --
    tryin to multitain  - Globus = Planet != Welt
    1. Hellihello

      »» Habe zwar bereits den Thread schon gefunden und wollte auch dort meine Frage reinsetzen, ging aber irgendwie nicht, weil ich den Antworte Button nicht fand, falls es überhaupt einen gibt.

      Welchen Thread?
      »»
      »» Ich bin der Anleitung soweit gefolgt und komme einfach nicht mehr weiter:

      Welche Anleitung?

      Das ist recht viel Code, wo genau liegt Dein Problem?

      Dank und Gruß,

      frankx

      Es gibt hier im Forum schon einen Thread mit der genau selben Überschrift, wie ich sie wählte. Schien aber bereits geschlossen zu sein.

      Das Problem ist auch als Kommentar im Quelltext angegeben.

      1. Hi,

        zitiere bitte nicht sinnfrei einfach "alles", sondern nur das, worauf du dich beziehst -

        Es gibt hier im Forum schon einen Thread mit der genau selben Überschrift, wie ich sie wählte.

        • und rueck doch einfach einen *Link* raus ... ist denn das so schwer?

        MfG ChrisB

        --
        „This is the author's opinion, not necessarily that of Starbucks.“
        1. Hi,

          zitiere bitte nicht sinnfrei einfach "alles", sondern nur das, worauf du dich beziehst -

          »» Es gibt hier im Forum schon einen Thread mit der genau selben Überschrift, wie ich sie wählte.

          • und rueck doch einfach einen *Link* raus ... ist denn das so schwer?

          MfG ChrisB

          Also echt. Das ist ja hier im Forum ein Umgangston.

          Da habt ihr Euren Link:
          http://forum.de.selfhtml.org/archiv/2008/2/t167140/

          Das Problem ist doch schon gelöst, der erste Quelltext ist der Fehlerhafte Code und das Problem ist auch eingegrenzt. Siehe auch Kommentare im Quelltext, man muss nur lesen.

          Die Funktion ist von einer Klasse und das Statement ist bis zu dem Punkt auch in Ordnung, steht auch im Quelltext als Kommentar.

          Der zweite Quelltext ist der von mir korrigierte auf Grundlage einer anderen Lösung aus einem anderen Forum:

          Da Link:
          http://www.php.net/mysqli_stmt_bind_result

          Die jegliche Frage lautet nur noch, warum es bei dem einen Quellcode zum Fehler kommt. Der Fehler liegt darin, dass nur das letzte Feld mit einem Wert belegt wird, die anderen sind leer.

          Und warum durch die kleinen Änderungen im zweiten Quelltext es nun geht.

          Und es gibt Leute, die arbeiten ganzen Tag an so nem Zeug. Da kann es mal vorkommen, dass vielleicht auch mal Fragen kommen, die nicht für Euch mundgerecht zusammengeschnitten ist. Nur kann man das auch etwas höflicher sagen. Gibt schließlich auch noch andere Foren ...

          1. Hellihello

            Also echt. Das ist ja hier im Forum ein Umgangston.

            Knappe, sachbezogene Aufforderungen, die Informationen so vorzubereiten, wie es 99% der erfolgreichen Frager hier auch tun. Reine Frage der Effizienz.

            Da habt ihr Euren Link:
            http://forum.de.selfhtml.org/archiv/2008/2/t167140/

            Das ist kein Link. Es wird ein bisschen "selbst"-Hilfe erwartet.
            Das ist ein Link:

            http://forum.de.selfhtml.org/archiv/2008/2/t167140/

            Der zweite Quelltext ist der von mir korrigierte auf Grundlage einer anderen Lösung aus einem anderen Forum:

            Da Link:

            http://www.php.net/mysqli_stmt_bind_result

            Die jegliche Frage lautet nur noch, warum es bei dem einen Quellcode zum Fehler kommt. Der Fehler liegt darin, dass nur das letzte Feld mit einem Wert belegt wird, die anderen sind leer.

            Und warum durch die kleinen Änderungen im zweiten Quelltext es nun geht.

            Und es gibt Leute, die arbeiten ganzen Tag an so nem Zeug. Da kann es mal vorkommen, dass vielleicht auch mal Fragen kommen, die nicht für Euch mundgerecht zusammengeschnitten ist. Nur kann man das auch etwas höflicher sagen. Gibt schließlich auch noch andere Foren ...

            Nun, wenn Du meinst. Frag ich mich, warum ich im Wesentlichen auch mit enormen zeitlichen Vorteilen hier qualifizierte Antworten auf eine Menge von Fragen bekomme und nicht wonanders. Ich kenne kein Forum, was so gut ist wie das hier. Inklusive User-Shaping. [kleiner Scherz]

            Dank und Gruß,

            frankx

            --
            tryin to multitain  - Globus = Planet != Welt
          2. Hallo,

            Die Funktion ist von einer Klasse und das Statement ist bis zu dem Punkt auch in Ordnung, steht auch im Quelltext als Kommentar.

            Ich lese in der einen Stunde, die ich am Tag Zeit hab, ca. 200 - 300 Postings (~20-30 Threads). Beschwerre dich bitte nicht, wenn ich bei einem langen Text abschalte

            Und es gibt Leute, die arbeiten ganzen Tag an so nem Zeug. Da kann es mal vorkommen, dass vielleicht auch mal Fragen kommen, die nicht für Euch mundgerecht zusammengeschnitten ist.

            Ich vermute mal, dass wir sie trotzdem beantworten sollen?

            Nur kann man das auch etwas höflicher sagen. Gibt schließlich auch noch andere Foren ...
            dann geh dahin, wenns dir hier nicht passt...

            mfg, Flo

            --
            sh:) fo:| ch:? rl:( br:^ n4:| ie:{ mo:| va:} de:> zu:} fl:{ ss:) ls:< js:|
  2. Nach der unter dem Link zu findende Anleitung habe ich nun ein paar Änderungen vorgenommen, und jetzt läuft es. Warum es so jetzt läuft, weiß ich allerdings nicht wirklich. Hänge heute auch schon lange dran rum. Vielleicht hat ja jemand mal kurz lust, es zu erklären. Würde mich freuen.

    Meine Lösung nun, vergleiche mit dem Code darüber:

      
      
      
    public function db_PS_select($stmt, $dataTyp=null, $sParams=null, $store=true)  
    {  
      // Array Variable  
      $values = array();  
      $result = array();  
    			  
    			  
      if ($dataTyp && $sParams)  
      {  
        $stmt = $this->db_PS_execute($stmt, $dataTyp, $sParams);  
      }  
    			  
    			  
      // Erhalte Metadaten vom Ergebnis des Statements  
      if (!$meta = $stmt->result_metadata())  
      {  
        // Fehlerbehandlung  
      }  
    			  
      while ($field = $meta->fetch_field())  
      {  
        $params[] = &$row[$field->name];  
      }	  
    						  
    			  
      if (!call_user_func_array(array($stmt, 'bind_result'), $params))  
      {  
        // Fehlerbehandlung  
      }  
    			  
    					  
      while ($stmt->fetch())  
      {  
        foreach($row as $key => $value)  
        {  
          $c[$key] = $value;  
        }  
      
        $result[] = $c;  
      }  
      
      			  
      return $result;  
    			  
    }  
      
    
    
    1. Hellihello,

      naja: woher kommt diese public function? Sie sollte ja Teil einer Klasse sein. Warum verlinkst Du nicht auf deinen bereits geschlossenen Thread?

      Und: warum versuchst Du nicht, dein Problem zu isolieren (=klitzekleiner Testcode)?

      Dank und Gruß,

      frankx

      --
      tryin to multitain  - Globus = Planet != Welt
  3. echo $begrüßung;

    Habe zwar bereits den Thread schon gefunden und wollte auch dort meine Frage reinsetzen, ging aber irgendwie nicht, weil ich den Antworte Button nicht fand, falls es überhaupt einen gibt.

    Nun ja, das funktioniert hier etwas anders als in anderen Foren oder Boards. Während dort (ohne Moderatoreneingriff) immer alles aktiv ist und man auch auf hornalte Threads antworten kann, gibt es hier quasi den Lesesaal und das Archiv. Letzteres ist durchsuchbar. Aber wenn du im Archiv antworten könntest, würde es keiner hören. Ebensowenig kann jemand alle Beiträge im Archiv kennen oder findet genau den, den du meinst. Deswegen kam die Bitte, die Fundstelle zu verlinken oder wenigstens als URL zu nennen.

    Ich bin der Anleitung soweit gefolgt und komme einfach nicht mehr weiter:

    Da ich damals geantwortet habe und mir einbilde, dass es auch funktioniert hat, schiebe ich mal das Nichtmehrfunktionieren auf eine Änderung in PHP. Zumindest vermute ich das, anders kann ich es mir momentan nicht erklären.

    Quelltext:

    Schön wäre es auch gewesen, wenn du dazugeschrieben hättest, dass du mysqli verwendest, und man diese Information nicht aus den verwendeten Methodennamen erraten muss. Es gibt nämlich auch noch PDO, das sieht auf den ersten Blick ähnlich aus.

    if (!$meta = $stmt->result_metadata())
    {
      // Fehlerbehandlung
    }

    Ich hoffe, die ist bei dir angemessen implementiert und nicht ebenfalls nur angedeutet :-)

    Doch nun zum Thema.

    while ($field = $meta->fetch_field())
      $values[$field->name] = null;

    Das soll bewirken, dass in $values ein Array entsteht, das genauso viele Elemente hat, wie es Spalten im Funktionsergebnis gibt. Dazu werden die Metadaten der Ergebnismenge befragt.

    foreach ($values as &$reference); //nix auszuführen

    Diese Schleife sollte eigentlich die Elemente in $values zu Referenzen machen, doch wenn man mal eine Kontrollausgabe in den Schleifenkörper hängt, sieht man nun (am &-Zeichen), dass die Referenz "wandert".

    foreach ($values as &$reference)
        var_dump();

    Hier versucht mir meine Erinnerung einzureden, dass die Referenzen einzeln bestehen blieben. Wie dem auch sei, sie tun es nicht (mehr), also muss eine andere Lösung her:

    while ($field = $meta->fetch_field())
        $values[$field->name] =& $values[$field->name];

    Und das ist auch noch kürzer als while plus foreach aus der ursprünglichen Lösung. Eigentlich erwartete ich eine Notice beim Lesezugriff auf rechts stehende $values[$field->name], denn dieses Element gibt es ja noch nicht. Doch sie bleibt aus. Stattdessen scheint mir, dass aufgrund der Referenz-Zuweisung zuerst ein neuer Wert $values[$field->name] angelegt wird und der dann erst als Referenz "an sich selbst" gebunden wird. Was da genau abläuft wird man sicher im kompilierten Bytecode sehen können. Wenn da mal jemand nachschauen könnte, der damit Erfahrung hat ...

    if (!call_user_func_array(array($stmt, 'bind_result'), $values))

    bind_result() will echte Variablen, Array-Elemente mag es nicht, es sei denn, es sind Referenzen. Der foreach-Trick funktioniert nicht (mehr), aber als Ergebnis bleibt eine Referenz auf dem letzten Element von $values übrig.

    // ALLE FELDER BLEIBEN LEER, AUßER DAS LETZTE!!!
    // DAS LETZTE FELD ERHÄLT KORREKTEN WERT

    Und deshalb hat das fetch()

    while ($stmt->fetch())

    immer nur das letzte Feld an $values anbinden können.

    // NUTZE ICH FOLGENDEN CODE ALTERNATIV, FUNKTIONIERT ES!
    $stmt->bind_result($rowThreadId, $rowThreadName, $rowKatId, $rowBenutzerId,
      $rowThreadStatus, $rowThreadAntworten, $rowThreadGesehen, $row);

    Hier hast du "ordentliche" Variablen verwendet, für eine solche Verwendung ist das Result-Binding ausgelegt. Will man jedoch eine Abstraktionsschicht bauen, die mit einer beliebigen Spaltenanzahl in der Ergebnismenge auskommen soll, so hat man ein Problem, diese an bind_result() zu übergeben. Man könnte vielleicht mit variablen Variablen Bind-Variablen in ausreichender Menge erzeugen, doch wie bekommt man sie an bind_result() übergeben, außer mit eval()? Ich denke die call_user_func_array()-Methode ist da die bessere Lösung.

    echo "$verabschiedung $name";