Verzweifelnder: ID aus MySQL Datenbank kommt als String und als Integer

Hallo Forum!

Ich habe ein PHP-Skript geschrieben, wo mittels PDO Daten aus einer MySQL Datenbank geholt und dann weiterverarbeitet werden. Lokal am Laptop mit XAMPP hat das problemlos funktioniert. Als ich das Ganze dann auf den richtigen Server hochgeladen und die Seite dann über das Internet aufgerufen habe, kam es aber zu einer Fehlermeldung.

Die Daten erhalte ich im Skript mit folgender Methode:

$this -> _O_handler -> fetchAll(PDO::FETCH_OBJ);

Mein Ergebnis ist also ein Array mit Objekten, deren Eigenschaften den Inhalten der Datenbankfelder entspricht.

Nun bin ich längere Zeit gesessen, bis ich herausgefunden habe, wo bei meinem Webspace das Problem liegt. Und ich weiß es jetzt. Der ID Wert des Datensatzes landet lokal als String in der Verarbeitung, während die ID am richtigen Server als Integer geliefert wird. (Also als der Variablentyp, der ja auch im Datenbankfeld für die ID eingetragen ist.)

Zum Fehler ist es deshalb gekommen, weil eine weiterverarbeitende Funktion einen String als übergebenen Wert erwartet und deshalb kam es zu diesem Type Error. Ich habe das ganz einfach gelöst, in dem ich die Werte aus der Datenbank vor der Weiterverarbeitung mit strval() bearbeite.

Mein Problem konnte ich somit lösen. Mich würde jetzt allerdings trotzdem interessieren, wieso die ID lokal mit XAMPP als String kommt und bei der Verarbeitung am Live Sever als Integer. Semantisch richtiger ist ja die 2. Variante, nachdem die ID ja auch als Integer in der Datenbank gespeichert ist.

Kann mir vielleiht jemand diese2 verschiedenen Settings erklären? Kann man sagen, dass die String Variante „falsch“ ist? Oder was passiert da bei XAMPP?

Liebe Grüße

Der Verzweifelnde

  1. Der ID Wert des Datensatzes landet lokal als String in der Verarbeitung, während die ID am richtigen Server als Integer geliefert wird.

    Das heißt die lokale Datenbank ist anders definiert als die auf dem Server?
    Das kann nur schiefgehen.

    Kann mir vielleiht jemand diese2 verschiedenen Settings erklären?

    Der die Datenbanken verschieden definiert hat, sollte das wissen 😀

    Kann man sagen, dass die String Variante „falsch“ ist?

    Wenn der Wert ein int ist, ja.

    1. Hallo Encoder!

      Danke für Deine Antwort!

      Das heißt die lokale Datenbank ist anders definiert als die auf dem Server? Das kann nur schiefgehen.

      Also das Feld für die ID ist natürlich in beiden Fällen Integer, AUTO_INCREMENT und unique.

      Der Rest der Analyse siehe meine Antwort an Rolf!

      Liebe Grüße

      Der Verzweifelnde

  2. Hallo Verzweifelnder,

    ist die DB lokal und am Server gleich definiert? Oder ist sie lokal int und am Server char?

    Ansonsten könnte ich mir das auch nicht erklären. Ob es in PHP da Versionsunterschiede gibt, könnte man noch recherchieren.

    Also:

    • Welche Deklarationen liegen in der DB für die ID Spalte vor?
    • Welche PHP-Versionen verwendest Du
    • Welche Datenbanken verwendest Du (MySQL oder MariaDB, welche Version genau)?

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf!

      Danke für Deine Antwort!

      Also das sind die lokalen Werte: (Mit XAMPP am Laptop)

      XAMPP for Windows 8.0.0
      PHP Version 8.0
      Server: 127.0.0.1 via TCP/IP
      Server-Typ: MariaDB
      Server-Version: 10.4.17-MariaDB - mariadb.org binary distribution
      Protokoll-Version: 10
      

      Und das sind die Werte am Server: (Bei meinem Webhoster)

      PHP Version 8.1
      Server: Localhost via UNIX socket
      Server-Typ: MariaDB
      Server-Version: 10.5.16-MariaDB-1:10.5.16+maria~focal-log - mariadb.org binary distribution
      Protokoll-Version: 10
      

      Sieht man daraus, wieso die ID ein mal als String kommt und ein mal als Integer?

      Liebe Grüße

      Der Verzweifelnde

      1. Hallo Verzweifelnder,

        Sieht man daraus, wieso die ID ein mal als String kommt und ein mal als Integer?

        Ja. Mit etwas Studium einer Quelle, die jeder PHP Programmierer auswendig lernen sollte, die aber vermutlich die wenigsten lesen.

        In PHP 8.1 incompatible changes / PHP Data Objects / MySQL Driver wird dargestellt, dass genau diese Änderung mit PHP 8.1 hinein gekommen ist.

        Dort steht auch ein möglicher Workaround, um die Rückwärtskompatibilität zu behalten. Der Schalter ATTR_STRINGIFY_FETCHES ist schon ewig drin, vermutlich um das Verhalten von MYSQL auch für andere DBs nachzubilden. Das kriege ich jetzt nicht mehr historisch aufgedröselt.

        Oder Du hebst das PHP in deinem XAMPP auf 8.1 an und passt deinen Code entsprechend an.

        Aus anderen Kommentaren entnehme ich, dass das wohl über Jahre ein Problem des MYSQL Treibers gewesen ist, der hat nie getypte Werte geliefert, immer nur Strings. Andere Datenbanken hatten früher schon getypte Werte. Und jetzt auf einmal ändert sich das - vermutlich mit der Abschaffung von libmysql und der Umstellung auf mysqlnd.

        Meine persönliche Ansicht: Diese Änderung hätte niemals per Default erfolgen dürfen - man hätte einen Schalter einfügen müssen um sie zu aktivieren. Mit einer Notice, dass man in einem Kompatibilitätsmodus läuft. Die irgendwann zur Warnung wird. Wie sie es auch sonst machen.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hi,

          Oder Du hebst das PHP in deinem XAMPP auf 8.1 an und passt deinen Code entsprechend an.

          Da die Test-Umgebung so nahe wie möglich an der Produktiv-Umgebung sein sollte, ist das die m.M.n. beste Lösung.

          cu,
          Andreas a/k/a MudGuard

        2. Hallo Rolf!

          Danke für Deine Mühen und die ausführliche Antwort!

          Somit ist meine Frage, woran dieses unterschiedliche Verhalten liegt, beantwortet!

          Liebe Grüße

          Der Verzweifelnde

        3. der hat nie getypte Werte geliefert, immer nur Strings.

          Manche Sprachen:
          halt… einen int kann man nicht an einen String zuweisen. Du machst hier was grundlegendes falsch, da machen wir gleich gar nicht weiter.

          Andere Sprachen:
          schreib einfach was du willst, ich mach irgendwas draus das du nur sehr schwer durchblicken kannst. Wenn dadurch woanders Chaos ausbricht, wirst du es lange nicht bemerken.

          Ich wundere mich seit ich PHP kenne, wie sich im Web ausgerechnet etwas durchsetzen kann das es einem so breit erlaubt Fehler zu machen.
          Dass die genauso verbreitete Datenbank diesen Schmu mitmacht kann man leider als konsequent ansehen, so traurig es auch klingt.

          1. Dass die genauso verbreitete Datenbank diesen Schmu mitmacht kann man leider als konsequent ansehen, so traurig es auch klingt.

            Das ist ungefähr genau so fair, wie den Kompressor dafür verantwortlich zu machen, dass das Schlauchboot bei 6 ATÜ geplatzt ist.

            Die API von MySQL gibt jedenfalls die Daten und den Datentyp an den Client zurück. Guckst Du

            https://dev.mysql.com/doc/c-api/8.0/en/mysql-stmt-fetch.html

  3. XAMPP ist eine, leider untaugliche „Testumgebung“, weil es für die genutzten Programme Einstellungen vornimmt, die mit der Realität auf faktisch allen anderen Systemen (und zu den Einstellungen derer Hersteller, wie PHP) divergieren.

    Das hier ist der Standard (bis PHP 8.0):

    $db->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true );
    

    (damit werden die Zahlen als Strings geliefert) → setze das auf false und Du bekommst alle Zahlen als solchewelche.

    Hint: Ein

    $db = new PDO( $dsn, $user, $pass );
    var_dump( $db->getAttribute );
    

    auf beiden Systeḿen zeigt Dir anhand des Unterschiedes, was los ist und ob meine Vermutung stimmt.