Ankündigung

Einklappen
Keine Ankündigung bisher.

Daten in php casten oder in der Datenbank

Einklappen

Neue Werbung 2019

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

  • Daten in php casten oder in der Datenbank

    hi,

    ich hoffe der beitrag passt hier her.
    es geht um das verhalten von PDO und mysqli bei prepared statements. Sie unterscheiden sich was das binden und casten der parameter angeht und ich habe mich gefragt, welche der beiden vorgehensweisen wohl richtiger ist.

    folgende zwei codes

    PHP-Code:
    $mysql=new mysqli('localhost','root','''test2');
    $driver=new mysqli_driver();
    $driver->report_mode=MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT;

    $mysql->real_query('SET SESSION sql_mode = \'STRICT_ALL_TABLES\';');

    $stmt=$mysql->prepare('insert into testtabelle (id) values (?)');
    $stmt->bind_param('i',$id);
    $id='789jkl';
    $stmt->execute(); 
    PHP-Code:
    $pdo=new PDO('mysql:host=localhost;dbname=test2','root');
    $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

    $pdo->exec('SET SESSION sql_mode = \'STRICT_ALL_TABLES\';');

    $stmt=$pdo->prepare('insert into testtabelle (id) values (?)');
    $id='789jkl';
    $stmt->bindParam(1,$id,PDO::PARAM_INT);
    $stmt->execute(); 
    das ist zwei mal das selbe statement. beide male soll '789jkl' an das statement als integer gebunden werden. eingetragen werden soll das in das id-feld der tabelle welches den datentyp INT hat.
    strict_all_tables bewirkt dass warnungen der datenbank zu fehlern werden. und ein fehler wird hier auch erwartet:
    Data truncated for column 'id' at row 1
    oder wenn wir 'jkl' einfügen wollen:
    Incorrect integer value: 'jkl' for column 'id' at row 1
    bei dem code von PDO wird der fehler geworfen, denn PDO ist die angabe des data types anscheinend egal und es schickt den Parameter unverändert an die datenbank.
    bei mysqli wird erst ein typecast zu int durchgeführt und dann ein integer an die datenbank geschickt. so erkennt die datenbank gar nicht das falsche werte angekommen sind. nur bei sehr großen zahlen wird nicht gecastet.

    nun frage ich mich welche schnittstelle sich hier richtiger verhält.

    ich denke PDO. es ist nicht aufgabe der datenbankschnittstelle zu casten. dadurch dass die daten wie sie sind bei der datenbank ankommen ist es möglich überhaupt den fehler zu sehen. mysqli "versteckt" den fehler.

    andererseits sollte so ein fehler vielleicht gar nicht erst bei der datenbank ankommen? ist es nicht aufgabe des programms die daten auf korrektheit zu prüfen und ja nach fall zu entscheiden ob ein typecast ok ist oder ob die daten zurückgewiesen werden sollen?
    in dem fall wäre es allerdings auch wieder nicht aufgabe der datenbankschnittstelle sondern schon davor. was mich zu meiner nächsten frage bringt: warum kann bzw muss man überhaupt datentypen angeben beim binden der parameter? (außer bei LOBs)

    eventuell ist es dann doch besser immer als datatype string anzugeben. wobei hier PDO auch wieder was komisches macht und castet
    PHP-Code:
    $id=789;
    $stmt->bindParam(1,$id,PDO::PARAM_STR);
    $stmt->execute();
    var_dump($id); // ergibt string '789' 
    man muss in dem fall aufpassen, dass man die variable $id erst nach bindParam definiert. dann wird auch nicht gecastet.

    lg
    dingsda
    liebe Grüße
    Fräulein Dingsda


  • #2
    PHP-Code:
    $stmt->bind_param('i',$id);
    $id='789jkl'
    Erstmal solltest du das korrigieren... Deklaration von $id sollte schon vor der Benutzung liegen.
    Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

    Kommentar


    • #3
      Zitat von lstegelitz Beitrag anzeigen
      Erstmal solltest du das korrigieren... Deklaration von $id sollte schon vor der Benutzung liegen.
      das ist hier problemlos möglich solange $id vor execute definiert wird. das liegt daran, dann nicht der inhalt von $id übergeben wird sondern nur eine refenz.
      wird im manual auch so gemacht http://www.php.net/manual/en/mysqli-stmt.bind-param.php

      im falle von PDO ist das z.b. auch die einzige möglichkeit das automatische casten der php-variable zum string zu verhinden wie ich in meinem letzten absatz schrieb.

      PHP-Code:
      $id=789;
      $stmt->bindParam(1,$id,PDO::PARAM_STR);
      $stmt->execute();
      var_dump($id); // ergibt string '789' 
      PHP-Code:
      $stmt->bindParam(1,$id,PDO::PARAM_STR);
      $id=789;
      $stmt->execute();
      var_dump($id); // ergibt int 789 
      edit: das casten der php-variable mag in den meisten fällen kein großes problem sein. aber ich mag es einfach nicht, wenn eine funktion solche seiteneffekte hat, die sie nicht haben sollte.
      liebe Grüße
      Fräulein Dingsda

      Kommentar


      • #4
        Eine Referenz wird doch nur übergeben, wenn man bei der Parameterübergabe das & davor macht oder nicht?
        Sprich so:
        PHP-Code:
        $stmt->bind_param('i',&$id); 
        Hier
        Die Jatravartiden auf Viltwodl VI können den Kram von dir auch nicht nachvollziehen

        Kommentar


        • #5
          Zitat von Moewe Beitrag anzeigen
          Eine Referenz wird doch nur übergeben, wenn man bei der Parameterübergabe das & davor macht oder nicht?
          Sprich so:
          PHP-Code:
          $stmt->bind_param('i',&$id); 
          Hier
          schau dir das beispiel dort genauer an.
          bei der funktionsdefinition muss & vor den parameter geschrieben werden. damit dieser als refenz übergeben wird.

          PHP-Code:
          function foo(&$var)
          {
              
          $var++;

          beim funktionsaufruf wird aber nicht & davor geschrieben.

          PHP-Code:
          $a=5;
          foo($a); 
          glaub vor php 5 war es noch so, dass auch beim funktionsaufruf &$var geschrieben wurde. jetzt wird dort aber eine warnung geworfen (steht auch weiter auf der verlinkten seite.
          liebe Grüße
          Fräulein Dingsda

          Kommentar


          • #6
            Zitat von Moewe Beitrag anzeigen
            PHP-Code:
            $stmt->bind_param('i',&$id); 
            Anmerkung: Das geht ab PHP5.4 nicht mehr.
            Standards - Best Practices - AwesomePHP - Guideline für WebApps

            Kommentar


            • #7
              Wenn mal kein Casten will: bindValue statt bindParam.
              Crashkurs zum Thema Rechtschreibung: normalerweise (normaler weise oder normaler weiße), Standard (Standart), eben (ebend)

              Kommentar

              Lädt...
              X