PDO bindParam datatype Konstanten

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

  • PDO bindParam datatype Konstanten

    Hallo Forum,

    ich habe eine Frage zu PDO Statements, im speziellen zur bindParam Methode. Laut Handbuch kann man ja dem bindParam Aufruf einen (optionalen) Datentyp als Parameter mitgeben.

    Parameter sind ja als Konstanten definiert, wie z.B. PDO::PARAM_INT oder PDO::PARAM_STR. Mir fehlen da aber in der Auflistung bei http://www.php.net/manual/en/pdo.constants.php ein paar essentielle Parameter, wie zum Beispiel der real oder numeric Datentypen, oder sowas wie date und time Datentypen.

    Meine Annahme, dass die Dokumentation lückenhaft ist, hat sich leider nicht bestätigt, denn z.B. einen Datentyp PDO::PARAM_NUMERIC/REAL/DATE/WTF scheint es nach meinen Tests wirklich nicht zu geben.

    Weiss da jemand mehr darüber? In mir wächst der Verdacht, dass ich den Absatz über die Reife von PDO in PHP überlesen habe, oder einen anderen essentiellen Abschnitt.

    Hintergrund über die Verwendung von preparted Statements war eigentlich zum einen die Übersichtlichkeit des Codes und der einfacheren Verhinderung von Injections. Durch die Bindung von Variablen zu Spalten in der Datenbank und zu bestimmten Datentypen wollte ich das eigentlich geschickt lösen, aber wie ich bereits sagte, irgendwie scheine ich den Absatz verpasst zu haben, der die fehlenden Datentypen erklärt.

    Vielleicht ist PDO aber auch einfach noch nicht so weit, als dass es wirklich produktiv eingesetzt werden kann. Die meisten Tutorials und Texte datieren zwischen 06 und 07 und kauen auch nur die Texte aus dem Handbuch wieder.

    Für jegliche Hinweise (PDO Tauglichkeit, fehlende Datentypen) bin ich dankbar, die Licht in die Sache bringen.

    Gruss Frank

  • #2
    Der optional anzugebene Datentyp bezieht sich nicht auf den Datentyp der Tabellenfelder sondern auf die Interpretation des PHP internen Typs - so auch die Manual:PDO ist also keinenfalls unausgereift, unfertig oder ungeeignet für den produktiv Einsatz. Vielmehr bietet es eine Möglichkeit auf das interne Handling einzuwirken - ein Beispiel:
    PHP-Code:
    $foo 'null';
    $bar null;

    $statement -> bindParam  ':foo'$fooPDO::PARAM_NULL );
    $statement -> bindParam ':bar'$bar ); 
    Beide Zeilen tun genau das selbe, sie setzten ein Feld auf NULL, soweit die Felder NULL sein dürfen. Eine explizite Angabe ist deshalb weder nötig noch gewünscht, denn einerseits möchtest du nicht Feldtypen wie DATE in PHP umsetzen, zum anderen ist es meist viel einfacher zum Beispiel execute zu benutzen um alle Paramter zu übergeben.
    Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

    Kommentar


    • #3
      Original geschrieben von tontechniker
      Der optional anzugebene Datentyp bezieht sich nicht auf den Datentyp der Tabellenfelder sondern auf die Interpretation des PHP internen Typs ...
      D.h. der angebene Datentyp dient lediglich zur Interpretationshilfe der PDO Klasse von diesen Datentypen, nämlich denen von PHP, und nicht meiner Datenbank, richtig? Und dass solche Datentypen wie floats fehlen, liegt an der Eindeutigkeit des Datentyps? Oder wie kann ich das verstehen?
      Analog zu deinem Beispiel, wie würde denn das Handling aussehen, wenn

      PHP-Code:
      $foo '1.78';
      $bar 1.78
      wäre. Bei dem Beispiel <<null>> ist es ja relativ einfach nachzuvollziehen, dass einmal der Zustand null bei einem Textfeld angewandt wird, d.h. das Feld wird geleert, und einmal 'null' als String in ein Textfeld eingefügt wird. Bei PDO::PARAM_INT ist mir das schon weit weniger klar, denn dann müsste es meinem Verständnis nach ja auch für weitere Datentypen diese Konstanten geben. Weiterhin steht im Handbuch

      PDO::PARAM_NULL (integer)
      Represents the SQL NULL data type.
      PDO::PARAM_INT (integer)
      Represents the SQL INTEGER data type.
      PDO::PARAM_STR (integer)
      Represents the SQL CHAR, VARCHAR, or other string data type.
      dem ich entnehme, dass die Datentypen dort die SQL Datentypen repräsentieren. Deshalb meine ursprüngliche Annahme, dass es da mehr geben müsste. Wie der geneigte Leser bemerkt, ist mir diese Sache so klar wie Rheinwasser nach einem Hochwasserereignis ...

      Um aber auf den Ursprung meiner Recherchen bezüglich PDO::PARAM_* zurückzukommen - inwieweit ist denn die Behandlung von Daten bei PDO notwendig, um SQL-Injections vorzubeugen?
      Ich weiss z.B. von der pg_convert Funktion bei den Postgresql Funktionen, dass da eine automatische Typumwandlung auf den entsprechenden Datentyp geschieht. pg_convert greift da auf die Tabellendefinition in der Datenbank zurück und gibt bei nicht möglicher Konvertierung einen Fehler aus. Passiert da ähnliches im Hintergrund bei der PDO Geschichte?

      PDO ist also keinenfalls unausgereift, unfertig oder ungeeignet für den produktiv Einsatz.
      Das ist doch mal ne Hausmarke. Da komme ich doch glatt auf dich zurück

      Kommentar


      • #4
        Und dass solche Datentypen wie floats fehlen, liegt an der Eindeutigkeit des Datentyps? Oder wie kann ich das verstehen?
        Also grundsätzlich hat SQL bei Querys ja sowieso nur zwei Typen Werte ohne und Werte mit Anführungszeichen, dass heißt eine SQL Engine kümmert sich intern um den richtigen Typen und die Entsprechung für den Feldtyp (MySQL setzt zum Beispiel '' wenn man versucht 'Blubb' in ein Feld des Typs Integer zu schreiben). Genau das gleiche gilt natürlich auch für Querys, die, als Pepared Statement oder normale Query, über PDO abgesetzt werden. Dass heißt PDO sendet da auch bei angegeben Typen nicht mehr an den SQL Server. Der angegeben Parameter geht direkt an den Zend Parser wo er zur Typenumwandlung dient - ein Ausschnitt aus pdo_stmt.c und zend_API.c:
        PHP-Code:
        static int register_bound_param(INTERNAL_FUNCTION_PARAMETERSpdo_stmt_t *stmtint is_param/* {{{ */
        {
        ...
            if (
        FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIETZEND_NUM_ARGS() TSRMLS_CC,
                    
        "lz|llz!", &param.paramno, &param.parameter, [b]&param.param_type[/b], &param.max_value_len,
                    &
        param.driver_params)
        ...
        }

        // Funktion die innerhalb von zend_parse_parameters_ex die Parameter umwandelt
        static char *zend_parse_arg_impl(int arg_numzval **argva_list *vachar **spec TSRMLS_DC)
        {
        ...
            switch (
        c) {
            case 
        's'// Zieltypp
                
        {
        ...
                    switch (
        Z_TYPE_PP(arg)) { // Ausgangstyp
                        
        case IS_NULL:
                            if (
        return_null) {
                                *
        NULL;
                                *
        pl 0;
                                break;
                            }
                        case 
        IS_STRING:
                        case 
        IS_LONG:
                        case 
        IS_DOUBLE:
                        case 
        IS_BOOL:
                            
        convert_to_string_ex(arg);
                            *
        Z_STRVAL_PP(arg);
                            *
        pl Z_STRLEN_PP(arg);
                            break;
        ...
                    }
                }
                break;
        ...

        Mit der Datenbank hat der angegebene Typ also nichts zutun - nur mit der Art der internen Behandlung. Es sind nicht alle Typen implementiert weil es bei einigen Typen keinen Unterschied macht was tatsächlich angegeben wird. Eine Typen angabe ist also im Prinzip nur beim Large Object Type interessant.
        Um aber auf den Ursprung meiner Recherchen bezüglich PDO::PARAM_* zurückzukommen - inwieweit ist denn die Behandlung von Daten bei PDO notwendig, um SQL-Injections vorzubeugen?
        Welche Art von SQL Injections sollte es dort geben? Wenn du mit Prepared Statements arbeitest hast du gar keine Probleme mit SQL Injections, da die Paramter ja erst nachträglich vom Server eingesetzt werden. Die Manual dazu:
        Zuletzt geändert von tontechniker; 22.05.2008, 20:15.
        Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

        Kommentar


        • #5
          Erst einmal vielen Dank für deine wirklich ausführlichen Antworten - ich denke, das Thema ist für mich jetzt klarer geworden.

          Code:
          ...
          case IS_STRING:
          case IS_LONG:
          case IS_DOUBLE:
          case IS_BOOL:
              convert_to_string_ex(arg);
          ...
          Die o.g. Typen werden also zu String konvertiert und die Datenbank entscheidet dann, was damit zu tun ist.
          Der Ausgangstyp wird mittels Z_TYPE_PP(arg) übergeben. Wobei Z_TYPE_PP ein Zend interner Pointer ist (Z_TYPE_PP -- Get type field from zval pointer pointer). Aber das wird mir zu dann zu Programmiersprachen-intern
          Dennoch verstehe ich das Konzept dahinter - denke ich


          ... Welche Art von SQL Injections sollte es dort geben? Wenn du mit Prepared Statements arbeitest hast du gar keine Probleme mit SQL Injections ...
          Vielen Dank, aber ich frage da lieber noch einmal mehr nach als nachher im Regen zu stehen. Auch wenn ich mich jetzt dunkel daran zu erinnern meine, den von dir zitierten Absatz zu Prepared Statements im Handbuch gelesen zu haben.

          Vielen Dank noch einmal für deine Mühe

          Kommentar

          Lädt...
          X