Ankündigung

Einklappen
Keine Ankündigung bisher.

Referenzen, mysqli_stmt::bind_param

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Referenzen, mysqli_stmt::bind_param

    Ich habe mysqli und mysqli_stmt erweitert und stehe vor einem Problem mit Referenzen:

    Dieser Code funktioniert, ist aber etwas unpraktisch:
    PHP-Code:
    class StmtMySQLi extends mysqli_stmt
    {
    // [...] weitere Methoden
        
    public function bindParameters($types,&$params)
        {
            
    $params = array();
            for (
    $i=1;$i<=$this->parameterCount();++$i) {
                
    $params[] = &${'p'.$i};
            }
            
    array_unshift($params,$types);
            return 
    call_user_func_array(array($this,'bind_param'),&$params);
        }

    PHP-Code:
    $stmt $db->prepare('INSERT INTO test (bla,blubb) VALUES (?,?)');
    $stmt->bindParameters('ss',$params);

    $params[1] = 'test';
    $params[2] = 'testest'
    Ich wünsche mir aber eine Verwendung wie
    PHP-Code:
    $params = array('test','testest'); 
    Mein Ansatz dafür:
    PHP-Code:
    class StmtMySQLi extends mysqli_stmt
    {
    // [...] weitere Methoden
        
    public function bindParameters($types,&$params)
        {
            
    $params = array();
            
    $args = array($types);
            for (
    $i=0;$i<$this->parameterCount();++$i) {
                
    $params[$i] = &${'p'.$i};
                
    $args[] &= $params[$i];
            }
            return 
    call_user_func_array(array($this,'bind_param'),&$args);
        }
        }

    Das funktioniert nicht. Auch nicht wenn ich es irgendwie umstelle. Ich habe innerhalb der for Schleife wirklich einiges versucht.

    Kann mir jemand etwas über Referenzen erzählen, das ich noch nicht weiß?

  • #2
    bind_param() "merkt" sich nur &${'p'.$i}
    Wenn Du $params das neue Feld array('test','testest') zuweist, hat das keinen Einfluss darauf, dass bind_param() Referenzen auf die urspünglichen &${'p'.$i} hat und die neuen Elemente des neuen Feldes haben keine Verbindung zu den ursprünglichen Variablen, die an bind_param() übergeben wurden.

    Kommentar


    • #3
      Dann möchte ich zumindest
      auf $param[0] zuweisen können, das klappt auch nicht.
      Ideen für eine bessere Lösung? Sollte ich lieber einen Methodenaufruf machen anstatt eine Referenz zuzuweisen?

      Kommentar


      • #4
        Zitat von Phlegma Beitrag anzeigen
        Sollte ich lieber einen Methodenaufruf machen anstatt eine Referenz zuzuweisen?
        Klingt für mich so spontan gut.
        Das würde ich direkt StmtMySQLi hinzufügen, also in der Form
        PHP-Code:
        $stmt->setParameterTypes('ss'); 

        $stmt->bind( array('test''testtest') );
        $stmt->execute();

        $stmt->bind( array('test2''testtest2') );
        $stmt->execute();

        // ggf. auch
        $stmt->execute( array('test3''testtest3') ); 
        Vielleicht auch
        PHP-Code:
        $stmt $db->prepareParameterizedQuery(
          
        'INSERT INTO test (bla,blubb) VALUES (?,?)',
          
        'ss'
        ); 
        Für prepareParameterizedQuery() fällt Dir sicherlich noch ein besserer Name ein - mir gerade nicht

        Kommentar


        • #5
          Alles schön und gut und wohl auch die Endlösung, doch bleibt das Rätsel offen warum der 2te Code nicht funktioniert.

          Kommentar


          • #6
            Weil bind_param keine Referenz auf das neue Feld bzw die neuen Elemente hat, sondern Referenzen auf die Variablen/Speicherstellen, die Du mit &${'p'.$i} erzeugt hast.

            Kommentar


            • #7
              Zitat von Phlegma Beitrag anzeigen
              Mein Ansatz dafür:
              PHP-Code:
              class StmtMySQLi extends mysqli_stmt
              {
              // [...] weitere Methoden
                  
              public function bindParameters($types,&$params)
                  {
                      
              $params = array();
                      
              $args = array($types);
                      for (
              $i=0;$i<$this->parameterCount();++$i) {
                          
              $params[$i] = &${'p'.$i};
                          
              $args[] &= $params[$i];
                      }
                      return 
              call_user_func_array(array($this,'bind_param'),&$args);
                  }
                  }

              PHP-Code:
              $stmt $db->prepare('INSERT INTO test (bla,blubb) VALUES (?,?)');
              $stmt->bindParameters('ss',$params);

              $params[0] = 'test';
              $params[1] = 'testest'

              Kommentar


              • #8
                Ja, und da bleibt das Feld $params das selbe Feld. Du änderst nur die Elemente. Und die sind Referenzen auf die Variablen, die Du mit &${'p'.$i} erzeugt hast und die Du bind_param() übergeben hast.

                Kommentar


                • #9
                  Aber sie sind doch alle referenziert?

                  Kommentar


                  • #10
                    Aber Du weist doch im zweiten Skript ein neues Feld mit neuen Elemente/Variablen zu.
                    bind_param hat keine Ahnung von dem Feld (weder vom neuen noch dem ursprünglichen). Es hat nur Referenzen auf die Elemente, die im ursprünglichen Feld waren.

                    Kommentar


                    • #11
                      Ich verstehe es immer noch nicht...

                      1. $params wird als Referenz direkt in die Methode gegeben, dabei erstellt.
                      2. $params wird innerhalb der Methode mit weiteren Referenzen gefüllt, damit ein Array der richtigen Größe entsteht um es per call_user_func_array an bind_param() zu schicken.

                      Im ersten Script (der funktioniert) wurde nun noch $types reingeschoben, weil es nunmal dazu gehört.
                      --
                      3. Die einzelnen Felder von $params werden auf ein anderes Array referenziert, damit $params nicht $types angefügt werden muss, damit diese $types nachher nicht unnötig rumfahren, und $params nicht ab [1] sondern ab [0] befüllt werden kann.

                      Wo gehen Referenzen verloren?

                      Eig sollte $params[$n] auf $args[$n+1] referenziert sein.

                      Kommentar


                      • #12
                        Nehmen wir mal zwei Parameter, $types='ss'. Die heißen dann p1 und p2.
                        Das, was die Variable ausmacht (den Speicher, wenn Du so willst), schreibe ich als [p1] bzw [p2]. Referenzen darauf als >p1< bzw >p2<.
                        Du erstellst also das Feld ('ss', >p1<, >p2<), das $args &= ist hier irrelevant.
                        Also rufst Du
                        Code:
                        call_user_func_array(array($this,'bind_param'), array('ss', >p1<, >p2<))
                        auf (das & vor args ist wieder irrelevant).
                        Das entspricht
                        Code:
                        $this->bind_param('ss', >p1<, >p2<)
                        Also "nur" Referenzen auf p1 und p2. Alles drumherum mit den ganzen Referenzzeichen hat keinerlei Bewandtnis für den Aufruf von bind_param. Es kennt wie gesagt keine Felder und keine Magie von call_user_func_array() macht die Parameter noch "referenziger".

                        Kommentar


                        • #13
                          Aber ich referenziere p1 und p2 doch genauso nach args. Wieso sind p1 params[0] und args[1] Nicht das selbe? kann man nur einmal referenzieren?!

                          Kommentar


                          • #14
                            Ok, also weiter.
                            $params wurde als Referenz an die Methode übergeben, also ist es nach dem Aufruf der Methode array(>p1<, >p2<).
                            Im ersten Skript greifst Du auf die Element zu und setzt neue Werte für diese Elemente.
                            PHP-Code:
                            $params[1] = 'test'
                            Also >p1<='test', der Wert von [p1] ist dann also 'test'. Für genau dieses [p1] hat bind_param eine Referenz gespeichert, wegen $this->bind_param('ss', >p1<, >p2<). Analog $params[1], [p2] und >p2<.
                            Änderst Du also $params[1], änderst Du die Variable, für die bind_param() eine Referenz gespeichert hat.
                            Beim zweiten Skript erstellst Du ein neues Feld, mit neuen Elementen.
                            $param = [neuesFeld([neuerWert], [neuerWert])]. Da taucht kein >p1< oder >p2< mehr auf. Deshalb hat das keinen Einfluss mehr auf Dein $stmt Objekt und das, was bind_param() gespeichert hat.

                            Kommentar


                            • #15
                              Wir reden aneinander vorbei, bzw. du verstehst mich nicht.
                              Schau dir nochmal genau Post #7 an.
                              Das $params = array(blablubb..); habe ich ja schon lange verstanden und aufgegeben.

                              Kommentar

                              Lädt...
                              X