ubuntuusers.de

PHP Fatal error: Uncaught PDOException / MariaDB

Status: Gelöst | Ubuntu-Version: Ubuntu 22.04 (Jammy Jellyfish)
Antworten |

Thomas_Do Team-Icon

Moderator
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

Ich hatte unter Ubuntu 20.04 lange Zeit ein PHP-Skript laufen. Nun bekomme ich unter Ubuntu 22.04 einen Fehler:

PHP Fatal error:  Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 in /var/www/html/fz/change_user.php:7\nStack trace:\n#0 /var/www/html/fz/change_user.php(7): PDOStatement->execute()\n#1 /var/www/html/fz/new_user.php(6): include('...')\n#2 {main}\n  thrown in /var/www/html/fz/change_user.php on line 7

Das eingebundende Skript:

1
2
3
4
5
6
7
8
9
<?php
//error_reporting(E_ALL);
//ini_set("display_errors", 1);
include 'config.php';
$id=$_POST['user_id'];
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id=$id");
$extr->execute();
echo "\nPDOStatement::errorInfo():\n";
$row_arr = $extr->fetch();

- PHP 8.1.2-1ubuntu2.14

- mariadb Ver 15.1 Distrib 10.6.16-MariaDB

Da ich von PHP und MySQL kaum Ahnung habe, das Skript aber wieder laufen soll, wäre ich für sachdienliche Hinweise sehr dankbar.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Zwei ganz wild ins Dunkle geschossene Vermutugen:

  • Hast Du sichergestellt, dass $dbtable wirklich einen Tabellennamen enthält? ($id könnte auch etwas Ungünstiges enthalten.)

  • Ist das Skript vielleicht ganz oder in Teilen mit Windows-Zeilenendungen geschrieben? dos2unix hilft.

Thomas_Do Team-Icon

Moderator
(Themenstarter)
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

rklm schrieb:

Zwei ganz wild ins Dunkle geschossene Vermutugen:

  • Hast Du sichergestellt, dass $dbtable wirklich einen Tabellennamen enthält? ($id könnte auch etwas Ungünstiges enthalten.)

config.php wird eingebunden. Und dort steht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
    /* Database Connection */

    $dbserver = 'localhost';
    $dbname = 'test_users';
    $dbtable = 'users';
    $dblogin = 'root';
    $dbpass = 'xxxxxxxxxxxxxxxx';

    try {
    $db = new PDO('mysql:host=' . $dbserver . ';dbname=' . $dbname . ';charset=utf8', $dblogin, $dbpass);
    } catch (PDOException $ex) {
    die('Fehler: '.$ex->getMessage());
   }

$id werde ich mir noch einmal genau anschauen.

  • Ist das Skript vielleicht ganz oder in Teilen mit Windows-Zeilenendungen geschrieben? dos2unix hilft.

Würde mich wundern, da ich nur unter Linux arbeite und das Skript ja bisher funktionierte. Habe aber dos2unix trotzdem darüberlaufen lassen aber ohne Effekt.

tshe

Anmeldungsdatum:
28. Juli 2023

Beiträge: 84

Der Code wirkt "etwas konfus" 😉 scheint aus mehreren Tutorials zusammengewürfelt zu sein.

In eine PDO-prepare gehören keine Abfrage-relevanten Variablen, sondern nur Platzhalter. Die Abfragevariable muss in execute rein.

Probier mal:

1
2
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id = ?");
$extr->execute($id);

tshe

Anmeldungsdatum:
28. Juli 2023

Beiträge: 84

Ach ja - ich kenne MariaDB nicht, und ob da eine andere Syntax verwendet wird. Denn das ".x." verwendet PHP eigentlich nur in Texten.

Der 2. Test wäre dann also:

1
2
$extr = $db->prepare("SELECT * FROM $dbtable WHERE user_id = ?");
$extr->execute($id);

Und wenn das nichts hilft, könnte es ev. an PHP8.1 liegen. Die Fehlersuche in PHP ist immer etwas frickelig.

Thomas_Do Team-Icon

Moderator
(Themenstarter)
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

tshe schrieb:

Der Code wirkt "etwas konfus" 😉 scheint aus mehreren Tutorials zusammengewürfelt zu sein.

Genauso ist das 😉. Wir brauchten schnell ein „benutzerfreundliches“ Frontend für die Datenbank und keiner hatte Ahnung.

Thomas_Do Team-Icon

Moderator
(Themenstarter)
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

rklm schrieb:

$id könnte auch etwas Ungünstiges enthalten.

Das war's. Die Variable war teilweise leer, hätte dann aber "0" enthalten sollen. Keine Ahnung warum das früher ging. Evtl. waren die älteren PHP-Versionen da weniger strikt.

Ich habe da jetzt eine Abfrage drin

if (empty($id)) $id = '0';

dann klapp's.

Vielen Dank allen für die Hilfe!

homer65

Avatar von homer65

Anmeldungsdatum:
8. November 2005

Beiträge: 574

Wohnort: bochum, germany

Bin beileibe kein PHP Experte, aber müßte es statt

1
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id=$id");

nicht

1
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id=" . $id);

sein?

tshe

Anmeldungsdatum:
28. Juli 2023

Beiträge: 84

homer65 schrieb:

Bin beileibe kein PHP Experte, aber müßte es statt

1
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id=$id");

nicht

1
$extr = $db->prepare("SELECT * FROM " . $dbtable . " WHERE user_id=" . $id);

sein?

Nein. Wie o.e. gehören generell keine Abfragevariablen in ein PDO-Statement.

Sowas ist eigentlich ein NoGo, und je nach PHP/DB-Umgebung funktioniert dieser Code auch gar nicht. Siehe dazu: : php.net PDO::prepare : Da werden sogar noch eckige Klammern angegeben; meine 2. Version oben funktioniert bei mir auch ohne. Welche Syntax funktioniert, wird man selbst testen müssen.

Wenn der Fokus aber auf "muss nur funktionieren liegt", ist doch egal was wie funktioniert - solange es funktioniert 😎 . Best-Practice, Stabilität & Sicherheit waren hier auch kein Thema, sondern: Fehler X! Hilfe? → Fehler gefunden & behoben → Funktioniert & Status: Gelöst → Also alles wunderbar 😇

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

tshe schrieb:

Nein. Wie o.e. gehören generell keine Abfragevariablen in ein PDO-Statement.

Genau. Der Witz von Prepared Statements ist ja gerade, dass man eine Anfrage nur ein Mal übersetzt (und ggf. planen lässt) und sie dann mehrfach mit verschiedenen Eingaben benutzen kann. Das ist effizienter als das SQL immer wieder parsen lassen zu müssen.

Antworten |