Software & Praxis

PDO und vorbereitete Abfragen: Werte, Sortierung und Suche trennen

Die Grenze zwischen SQL-Struktur und Datenwerten an einem eigenständigen PHP-Beispiel mit unabhängiger Ergebnisprüfung verstehen.

Eine präzise Metallvorlage mit PDO und dem Parameterplatz :term steht getrennt von einer Suchwertkarte CSS_ auf roter Unterlage. Das Motiv veranschaulicht feste SQL-Struktur und variable Daten.

Vorbereitete Abfragen mit PDO trennen die SQL-Struktur von übergebenen Datenwerten. Das ist eine wichtige Grundlage für nachvollziehbare Datenbankzugriffe mit PHP. Die Trennung funktioniert allerdings nur, wenn fremde Inhalte tatsächlich als Werte gebunden werden. Ein vorher aus ungeprüften Zeichenfolgen zusammengesetzter SQL-Befehl wird nicht allein dadurch zuverlässig, dass anschließend prepare aufgerufen wird.

Dieser Beitrag entwickelt eine kleine Katalogsuche mit Kategorie, Suchtext, Sortierung und Ergebnisgrenze. Der Code wurde mit einem künstlichen SQLite-Datenbestand ausgeführt. Besonders interessant sind Stellen, an denen ein Platzhalter nicht die ganze Aufgabe löst: Spaltennamen sind Struktur, ein Prozentzeichen besitzt innerhalb eines LIKE-Musters eine eigene Bedeutung und ein gebundener Wert ist noch keine fachlich passende Eingabe.

Werte und Struktur ausdrücklich unterscheiden

Bei einer Suchanfrage sind der gewünschte Begriff und die ausgewählte Kategorie Daten. Der Tabellenname, die ausgewählten Spalten und die Reihenfolgeanweisung sind Teile des Befehls. Diese Unterscheidung sollte im Quelltext sichtbar bleiben. Sonst entsteht schnell eine unübersichtliche Mischung aus SQL-Stücken, Anführungszeichen und fremden Werten, deren Bedeutung sich bei kleinen Erweiterungen schwer prüfen lässt.

Die PDO-Dokumentation zu prepare beschreibt Platzhalter für vollständige Datenliterale. Sie stehen nicht allgemein für beliebige SQL-Abschnitte. Im Beispiel kann deshalb der Suchwert an :term gebunden werden. Eine gewünschte Sortierspalte wird dagegen über eine feste Zuordnung ausgewählt. Ein Platzhalter für einen Spaltennamen würde nicht dieselbe Aufgabe erfüllen.

Die Trennung begrenzt auch die Aufmerksamkeit beim Review. Für Datenwerte wird geprüft, ob sie fachlich zulässig sind und passend gebunden werden. Für variable Struktur wird geprüft, welche festen Möglichkeiten die Anwendung überhaupt anbietet. Ein fremder Wert soll weder eine neue Tabelle auswählen noch hinter einer Sortieranweisung zusätzlichen SQL-Text ergänzen können.

Den Suchvertrag vor der Abfrage festlegen

EingabeRegel im BeispielVerwendung
qBis zu 80 Unicode-Codepunkte ohne ASCII-SteuerzeichenWörtlicher Teil des Titels
categoryall, web, code oder designBekannte Kategorie oder keine Einschränkung
sorttitle oder durationAuswahl einer festen Sortieranweisung
limitKanonische ganze Zahl von 1 bis 50Gebundene maximale Zeilenzahl

Die Suche soll einen wörtlichen Teil des Titels finden. Wer ein Prozentzeichen eingibt, sucht also nach einem tatsächlich vorhandenen Prozentzeichen. Eine Eingabe wie CSS_ soll nicht automatisch jedes beliebige Zeichen an der Stelle des Unterstrichs erlauben. Diese Entscheidung ist eine Produkteigenschaft unserer Suche. Eine andere Anwendung kann ausdrücklich eine Mustersprache anbieten. Dann muss sie diese ebenso klar erklären.

Der künstliche Katalog enthält 24 Einträge, darunter HTML 100%, CSS_Aufbau und JavaScript!. Es gibt außerdem doppelte Titel und gleiche Dauern. Dadurch lassen sich nicht nur passende Treffer, sondern auch die eindeutige Reihenfolge prüfen. Sämtliche Einträge sind frei erfundene Lernressourcen. Es handelt sich weder um Kundenangebote noch um eine Auswertung eines tatsächlichen Kursbestands.

Ein leerer Suchtext ist in diesem Vertrag erlaubt. Zusammen mit all entsteht eine begrenzte Anfangsliste statt einer Fehlermeldung. Das sollte im Produkt bewusst entschieden sein, weil eine andere Anwendung möglicherweise erst nach einer konkreten Eingabe suchen möchte. Leerer Text und fehlende Berechtigung sind jedenfalls verschiedene Sachverhalte. Die begrenzte Anfangsliste unseres Lernkatalogs enthält ausschließlich die künstlichen öffentlichen Ressourcen und erweitert keine fremde Zugriffsberechtigung.

Die Verbindung als eigene Voraussetzung behandeln

Die Suchfunktion erhält ein bereits konfiguriertes PDO-Objekt. Im ausgeführten Versuch wurde eine neue SQLite-Datenbank im Speicher aufgebaut und ausdrücklich der Ausnahmemodus gewählt. Es gibt keine Verbindung zu einem externen Server und keine Zugangsdaten. Die vorbereitete Leseabfrage arbeitet anschließend auf der bekannten Tabelle resources. Ihr Aufbau ist Teil der Lernumgebung.

$db = new PDO('sqlite::memory:', null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

Für eine produktive Anwendung werden Verbindungsdaten und Rechte gesondert eingerichtet. Die ausführende Identität sollte nur die für ihre Aufgabe benötigten Rechte besitzen. Der gezeigte Datenbestand wird im Test erstellt und anschließend gelesen. Daraus folgt keine Empfehlung, einen öffentlichen Suchendpunkt mit einer Identität für Schemaänderungen zu betreiben oder Zugangsdaten in Besucherantworten auszugeben.

Die vollständige geprüfte Suchfunktion

Die Funktion erwartet ein Eingabearray mit optionalen bekannten Feldern. Sie ist kein HTTP-Endpunkt und gibt keine fertige HTML-Seite aus. Diese begrenzte Form macht den Datenzugriff unabhängig prüfbar. Eine tatsächliche Webanwendung kann davor ihren Anfrageadapter und danach ihre Ausgabedarstellung ergänzen. Dabei bleiben deren eigene Zuständigkeiten erhalten.

<?php
declare(strict_types=1);

function searchResources(PDO $db, array $input): array {
    $defaults = ['q' => '', 'category' => 'all', 'sort' => 'title', 'limit' => '20'];
    if (array_diff(array_keys($input), array_keys($defaults))) {
        throw new InvalidArgumentException('Unknown search field');
    }
    $values = $defaults;
    foreach ($input as $key => $value) {
        if (!is_string($value) || strlen($value) > 512) {
            throw new InvalidArgumentException('Expected bounded scalar string');
        }
        $values[$key] = $value;
    }
    if (!preg_match('/\A.{0,80}\z/us', $values['q'])
        || preg_match('/[\x00-\x1F\x7F]/', $values['q'])) {
        throw new InvalidArgumentException('Invalid search text');
    }
    if (!in_array($values['category'], ['all', 'web', 'code', 'design'], true)) {
        throw new InvalidArgumentException('Unknown category');
    }
    $orders = [
        'title' => 'title COLLATE NOCASE ASC, id ASC',
        'duration' => 'duration_minutes ASC, id ASC',
    ];
    if (!isset($orders[$values['sort']])
        || !preg_match('/\A(?:[1-9]|[1-4][0-9]|50)\z/', $values['limit'])) {
        throw new InvalidArgumentException('Invalid order or limit');
    }
    // These are LIKE-pattern escapes, not manual SQL quoting.
    $pattern = '%' . strtr($values['q'], ['!' => '!!', '%' => '!%', '_' => '!_']) . '%';
    $sql = "SELECT id, title, category, duration_minutes FROM resources WHERE title LIKE :term ESCAPE '!'";
    if ($values['category'] !== 'all') { $sql .= ' AND category = :category'; }
    $sql .= ' ORDER BY ' . $orders[$values['sort']] . ' LIMIT :row_limit';
    $statement = $db->prepare($sql);
    $statement->bindValue(':term', $pattern, PDO::PARAM_STR);
    if ($values['category'] !== 'all') {
        $statement->bindValue(':category', $values['category'], PDO::PARAM_STR);
    }
    $statement->bindValue(':row_limit', (int)$values['limit'], PDO::PARAM_INT);
    $statement->execute();
    return $statement->fetchAll(PDO::FETCH_ASSOC);
}

Vor den fachlichen Regeln werden übergebene Werte auf skalare Zeichenfolgen und eine kleine Byteobergrenze geprüft. Danach folgt die eigentliche Text-, Kategorien-, Sortier- und Zahlenregel. Eine fehlende optionale Angabe erhält ihren dokumentierten Standardwert. Ein vorhandener, aber ungültiger Wert wird dagegen nicht stillschweigend durch einen zufällig passenden Standard ersetzt. Das erleichtert die Diagnose fehlerhafter Aufrufer.

Was eine Bindung tatsächlich leistet

Der vorbereitete Befehl enthält feste Parameterpositionen. Über bindValue werden die angenommenen Werte zugeordnet. Der Suchbegriff und die Kategorie erhalten einen Zeichenfolgentyp, die bereits geprüfte Ergebnisgrenze einen Ganzzahltyp. Die PDO-Dokumentation zu bindValue beschreibt diese Übergabe. Im Beispiel erfolgt die fachliche Prüfung ausdrücklich vor der Bindung.

Ein Typkennzeichen ersetzt diese Prüfung nicht. Unser Code akzeptiert etwa nicht einfach jede Zeichenfolge, die nach einer Umwandlung irgendwie wie eine kleine Ganzzahl aussieht. Erst die kanonische Darstellung von eins bis fünfzig wird angenommen und anschließend umgewandelt. Auf diese Weise bleibt nachvollziehbar, welche Eingaben der Schnittstellenvertrag tatsächlich erlaubt.

Im Versuch wurde zusätzlich eine vermeintliche Spalte als gebundener Wert an eine SELECT-Anweisung übergeben. Das Ergebnis war die Zeichenfolge title und nicht der Inhalt der Tabellenspalte title. Diese tatsächlich ausgeführte Gegenprobe macht den Unterschied zwischen Literal und Struktur anschaulich. Sie ist kein Ersatz für eine Datenbankdokumentation, verhindert aber ein häufiges Missverständnis beim ersten Umgang mit Platzhaltern.

Sortierungen über feste Möglichkeiten auswählen

Die Zuordnung orders enthält nur zwei feste SQL-Fragmente. title steht für eine nach Titeln geordnete Liste, duration für die Dauer. Beide ergänzen die ID als zweite Sortierstufe. Der fremde Auswahlwert wird nicht unmittelbar in den Befehl geschrieben. Er dient nur als Schlüssel für die vorhandene Zuordnung. Unbekannte Schlüssel werden abgelehnt.

Die OWASP-Empfehlungen zur SQL-Injection-Prävention erläutern diese Kombination aus gebundenen Datenwerten und festen strukturellen Auswahlmöglichkeiten. Unsere Zuordnung enthält nicht jede denkbare Spalte der Tabelle. Sie beschreibt nur die beiden fachlich angebotenen Sortierungen. Eine syntaktisch vorhandene Datenbankspalte wird dadurch nicht automatisch zur öffentlich auswählbaren Möglichkeit.

Die zweite Sortierstufe ist für gleiche Titel oder gleiche Dauern wichtig. Ohne sie könnte eine begrenzte Liste innerhalb gleichwertiger Einträge unterschiedlich ausfallen. Der Testbestand enthält solche Gleichstände absichtlich. Die unabhängig berechnete Referenz kontrolliert deshalb die vollständige Zeilenreihenfolge und nicht nur eine Menge von IDs oder die Anzahl der gefundenen Treffer.

LIKE hat eine eigene Mustersprache

Ein sicher gebundener Suchwert kann fachlich trotzdem eine zu breite Treffermenge erzeugen. Bei LIKE steht Prozent für eine beliebig lange Zeichenfolge und Unterstrich für ein einzelnes Zeichen. Diese Bedeutung gehört zur Musterverarbeitung innerhalb eines Datenwerts. Sie ist von der Frage getrennt, ob der Wert die äußere SQL-Struktur verändern darf.

Die Funktion verwendet deshalb ein ausdrücklich gewähltes Escapezeichen: das Ausrufezeichen. Aus einem eingegebenen Prozentzeichen wird im Muster !%, aus einem Unterstrich !_ und aus einem eingegebenen Ausrufezeichen !!. Erst danach werden die beiden von der Anwendung gewünschten äußeren Prozentzeichen ergänzt. Sie erlauben den wörtlichen Suchtext an einer beliebigen Position des Titels.

Die SQLite-Dokumentation zu LIKE und ESCAPE beschreibt diese Musterbedeutung. Das resultierende vollständige Muster wird weiterhin als einzelner Parameter gebunden. Es wird nicht als SQL-Text eingesetzt. Die eigene Zeichenbehandlung ist daher keine handgeschriebene allgemeine SQL-Maskierung. Sie setzt eine konkrete fachliche Suchregel innerhalb des gebundenen Datenwerts um.

Tatsächlich beobachtete PDO-Abfrage: Der Unterstrich wird zum gebundenen LIKE-Muster %!_%. Feste SQL-Struktur und Sortierung bleiben getrennt. Der künstliche Katalog liefert die Datensätze 3 und 11.
Die unveränderte Suchfunktion wurde mit einem Unterstrich als Suchtext ausgeführt. Die tatsächlich beobachtete SQL-Vorlage bindet das Muster %!_% als Zeichenkette und die Ergebnisgrenze 50 als Ganzzahl. Im künstlichen Katalog mit 24 Einträgen werden die Datensätze 3 und 11 gelesen. Das Beispiel belegt weder Berechtigungen noch die Laufzeit anderer Datenbanken.

Wörtliche Zeichen an tatsächlichen Treffern prüfen

Die Suche nach Prozent fand im ausgeführten Katalog die IDs 1, 23 und 11. Unterstrich fand 3 und 11. Ausrufezeichen fand 5, 24 und 11. Die Reihenfolgen entsprechen der angebotenen Titelsortierung. Es wurden nicht sämtliche Katalogzeilen gefunden. Der Test macht damit sichtbar, dass diese Zeichen im Beispiel tatsächlich wörtlich behandelt werden.

Eine weitere künstliche Ressource trägt einen SQL-ähnlichen Titel. Die Suche nach x' OR 1=1 -- lieferte genau deren ID 12. Der Text wurde als Inhalt gesucht und nicht als Bedingung ausgeführt. Gleichzeitig blieb die Tabelle mit allen 24 Zeilen erhalten. Solche anschaulichen Gegenproben belegen das Verhalten des konkreten Beispiels, ohne daraus eine allgemeine Zusage für beliebigen später ergänzten SQL-Code abzuleiten.

Unicode und Kollation fachlich einordnen

Der Suchtext muss gültiges UTF-8 sein und darf höchstens achtzig Codepunkte enthalten. Seine Byteobergrenze wird zusätzlich vorher betrachtet. Diese beiden Grenzen lösen unterschiedliche Aufgaben. Die erste begrenzt die fachliche Textlänge, die zweite vermeidet hier unnötig große Werte vor der weiteren Verarbeitung. Keine der beiden bestimmt automatisch, welche Groß- und Kleinschreibung die Datenbank miteinander gleichsetzt.

Im tatsächlich verwendeten SQLite-Verhalten werden ASCII-Groß- und Kleinbuchstaben bei LIKE standardmäßig zusammengeführt. Für darüber hinausgehende Unicode-Zeichen gilt das nicht allgemein. Entsprechend fand Über im Test ID 9 und über ID 10. Die beiden erfundenen Einträge wurden nicht automatisch gleichgesetzt. Eine sprachlich passende Suchfunktion benötigt deshalb eine bewusste Entscheidung über Kollation und gegebenenfalls zusätzliche Suchwerkzeuge.

Auch die Sortieranweisung COLLATE NOCASE ist im Beispiel eine SQLite-spezifische Festlegung. Sie darf nicht stillschweigend als allgemeine deutsche Wörterbuchsortierung beschrieben werden. Akzente, zusammengesetzte Zeichen und andere Sprachen benötigen eine genauere Betrachtung. Vor einer Übernahme in ein anderes System wird die tatsächliche Produktanforderung formuliert und mit dessen Verhalten verglichen.

Kategorien und Begrenzungen gezielt ergänzen

Für all entfällt die zusätzliche Kategorienbedingung. Bei einer bekannten konkreten Kategorie ergänzt die Anwendung einen festen Vergleich mit einem eigenen Platzhalter. Dadurch wird derselbe benannte Parameter nicht mehrfach in derselben Vorlage verwendet. Die PDO-Dokumentation weist auf die Unterschiede bei mehrfach verwendeten Namen und emulierten Vorbereitungen hin. Kleine eindeutige Vorlagen sind an dieser Stelle leichter zu prüfen.

Die Ergebnisgrenze wird ebenfalls gebunden. Sie bleibt eine angenommene Zahl und keine freie LIMIT-Zeichenfolge. Eine hohe zulässige Grenze wäre trotzdem eine Betriebsentscheidung. Der Beispielwert fünfzig ist keine allgemeingültige Grenze für schnelle Antworten. Die Dauer einer Suche hängt zusätzlich von Datenmenge, Zugriffspfad, Suchmuster und tatsächlicher Serverlast ab. In diesem Versuch wurden keine Laufzeiten gemessen.

Fehler von leeren Ergebnissen unterscheiden

Eine gültige Suche ohne Treffer gibt ein leeres Array zurück. Eine ungültige Eingabe löst dagegen eine InvalidArgumentException aus. Ein Datenbankproblem wird im gewählten PDO-Modus als PDOException weitergegeben. Der Versuch überprüfte das mit einer gesonderten Datenbank ohne die erwartete Tabelle. Ein fehlendes Schema wurde somit nicht als leere erfolgreiche Suche ausgegeben.

Die PDO-Dokumentation zur Fehlerbehandlung beschreibt den Ausnahmemodus. In einer wirklichen Webseite wird an einer geeigneten äußeren Stelle entschieden, welche verständliche Antwort Besucher erhalten und welche technischen Angaben intern benötigt werden. Ein vollständiger Verbindungsfehler samt Pfaden und Zugangsinformationen gehört nicht ungeprüft in eine öffentliche Fehlermeldung.

SQLite und MySQL nicht gleichsetzen

PDO bietet eine gemeinsame Aufrufoberfläche, macht aber nicht sämtliche SQL-Ausdrücke und Datenbankeigenschaften identisch. Die hier gezeigte Funktion wurde mit SQLite 3.53.4 und PHP 8.4.27 ausgeführt. Ein MySQL-Server wurde dafür nicht gestartet. Die Sortierkollation und das konkrete Suchverhalten müssen vor einer Übernahme angepasst und mit dem tatsächlich verwendeten Treiber überprüft werden.

Die MySQL-8.4-Dokumentation zu vorbereiteten Anweisungen erläutert serverseitige Unterstützung und unterscheidet Programmierschnittstellen von den SQL-Befehlen PREPARE und EXECUTE. Das ist keine Aufforderung, diese SQL-Befehle zusätzlich um jeden PDO-Aufruf zu legen. Für eine konkrete PHP-Verbindung werden deren Treiber und Einstellungen untersucht, einschließlich der Frage, welche Vorbereitung tatsächlich verwendet wird.

Wiederverwendung nicht als ungeprüftes Leistungsversprechen verkaufen

Die PHP-Einführung zu vorbereiteten Anweisungen zeigt die wiederholte Ausführung mit unterschiedlichen Werten. Das ist für wiederkehrende Vorgänge nützlich. Unsere Suchfunktion bereitet ihren Befehl jedoch innerhalb jedes Funktionsaufrufs vor. Der Versuch beweist deshalb weder eine konkrete Einsparung durch wiederverwendete Statements noch eine bestimmte Anfragegeschwindigkeit.

Wenn ein tatsächlicher Ablauf viele gleichartige Abfragen benötigt, kann die Lebensdauer eines Statements gesondert organisiert werden. Dabei bleibt zu prüfen, welche Verbindung und welche Vorlage weiterverwendet werden und wann ein Cursor geschlossen werden muss. Diese Betriebsfragen sollten anhand des realen Arbeitsablaufs beantwortet werden. Die Datenbindung dient hier zunächst der klaren Trennung zwischen Befehlsstruktur und Werten.

Den tatsächlichen Prüfumfang benennen

Der Versuch bestand 381 Prüfungen. Davon vergleichen 360 Fälle die vollständigen SQL-Ergebnisse mit einer unabhängig in PHP berechneten Referenz. Kombiniert wurden fünfzehn Suchtexte, vier Kategorieauswahlen, zwei Sortierungen und drei Grenzen. Die Referenz filtert die ursprünglichen Datensätze, ordnet sie nach derselben ausdrücklich beschriebenen Fachregel und begrenzt die Liste erst danach.

Weitere sechzehn Fälle prüfen abgelehnte Eingaben. Dazu gehören Arrays, unbekannte Kategorien, ein als Sortierung angebotener SQL-Befehl, falsche Zahlenschreibweisen, Steuerzeichen und ungültiges UTF-8. Fünf zusätzliche Prüfungen betreffen Standardgrenze, unveränderten Datenbestand, Integrität, die Literal-Gegenprobe und die weitergereichte Datenbankausnahme. Sämtliche Werte und Ergebnisse sind dem gespeicherten Prüfprotokoll zugeordnet.

Diese Zahlen beschreiben den tatsächlichen Versuch und keine Erfolgsquote für beliebige Datenbankanwendungen. Es wurden weder ein HTTP-Endpunkt noch Nutzeranmeldung, mehrmandantige Berechtigungen oder gleichzeitige Zugriffe getestet. Für private Datensätze muss eine Anwendung die zugriffsberechtigte Identität aus einem vertrauenswürdigen Kontext übernehmen. Ein frei übermitteltes Kategoriefeld wäre dafür kein Ersatz.

Den Ergebnisumfang genauso bewusst wählen

Die SELECT-Liste benennt vier benötigte Spalten ausdrücklich. Ein später ergänztes internes Bemerkungsfeld würde dadurch nicht automatisch Teil des Rückgabearrays. Diese Eigenschaft ist für Schnittstellen hilfreich, deren Ausgabe im Laufe der Zeit sonst unbemerkt wachsen könnte. Es bleibt trotzdem erforderlich, die gewählten Inhalte vor ihrer Verwendung zu beurteilen. Eine passende Spaltenliste ist eine nachvollziehbare Begrenzung, aber kein vollständiges Berechtigungssystem.

Auch ein erfolgreich gelesener Titel bleibt zunächst Dateninhalt. Würde eine Webansicht ihn später darstellen, müsste sie den konkreten HTML-Kontext passend behandeln. Eine vorbereitete SQL-Abfrage übernimmt diese Aufgabe nicht. Der hier getestete Baustein gibt nur Arrays zurück und enthält keine Browserdarstellung. Eine darauf aufbauende Oberfläche bekommt deshalb eigene Tests für Textausgabe, Fehlermeldungen und Bedienung. Die Prüfungen sollten genau der Schicht zugeordnet bleiben, in der sie tatsächlich durchgeführt wurden.

Erweiterungen nicht als freie SQL-Fragmente annehmen

Eine spätere Mehrfachauswahl von Kategorien wäre eine Änderung des Eingabevertrags. Ein einzelner Platzhalter nimmt nicht einfach eine beliebige Liste von SQL-Werten auf. Für eine solche Erweiterung werden zunächst Anzahl, erlaubte Einträge und das Verhalten einer leeren Auswahl festgelegt. Danach erhält jeder benötigte Wert eine passende Parameterposition. Unsere kleine Suchfunktion nimmt eine solche Liste ausdrücklich nicht an. Ein Array im Kategorienfeld gehört zu den geprüften Ablehnungsfällen.

Ähnlich wird eine neue Suchoption nicht dadurch sicher, dass sie hinter dem Namen „Filter“ versteckt wird. Ein Aufrufer sollte keine beliebige WHERE-Bedingung mitsenden dürfen. Die Anwendung beschreibt stattdessen konkrete fachliche Optionen und übersetzt jede in feste bekannte Struktur. Das erleichtert später auch die Prüfung, ob mehrere Filter gemeinsam eine sinnvolle Aufgabe beschreiben. Eine ausufernde Sammlung freier Textfragmente würde diese Zuordnung wieder verlieren.

Schließlich muss eine neue Detailansicht ihre eigene Datenfreigabe prüfen. Eine private Ressource wird nicht allein deshalb zugänglich, weil ihre ID als sauber gebundene Zahl übermittelt wurde. Die ID beschreibt das angefragte Objekt. Die zulässige Auswahl ergibt sich aus dem vertrauenswürdig festgestellten Nutzerkontext und den Regeln der Anwendung. Diese fachliche Entscheidung wird außerhalb der hier ausschließlich öffentlichen künstlichen Katalogsuche umgesetzt. Sichere Wertübergabe und erlaubter Datenzugriff ergänzen einander.

Checkliste für den nächsten PDO-Zugriff

  • Fachliche Filter, Suchbedeutung und Ergebnisordnung sind ausdrücklich festgelegt.
  • SQL-Struktur und fremde Datenwerte sind im Code getrennt sichtbar.
  • Platzhalter repräsentieren vollständige Werte und keine Spaltennamen.
  • Variable Sortierungen stammen aus einer kleinen festen Zuordnung.
  • Typen und Grenzen werden vor der Bindung fachlich geprüft.
  • LIKE-Sonderzeichen erhalten die vom Produkt gewünschte Bedeutung.
  • Gleiche Sortierwerte besitzen eine eindeutige zweite Ordnung.
  • Unicode- und Kollationsverhalten wurden mit passenden Fällen untersucht.
  • Ungültige Eingaben und Datenbankfehler werden nicht als leere Erfolge ausgegeben.
  • Verbindungsrechte und fachliche Zugriffsberechtigungen werden gesondert geregelt.
  • Treiberunterschiede sind vor einer Übernahme tatsächlich geprüft.
  • Leistungsbehauptungen beruhen auf passenden Messungen statt auf dem Namen einer API.

Gemeinsam weiterdenken

Was möchten Sie bewegen?

Eine Idee, eine konkrete Aufgabe oder der nächste Schritt mit KI. Wir hören zu.

Sprechen wir darüber