Access
 sql >> Datenbank >  >> RDS >> Access

Warum Sie PHPs PDO für den Datenbankzugriff verwenden sollten

Viele PHP-Programmierer haben den Zugriff auf Datenbanken gelernt, indem sie entweder die MySQL- oder MySQLi-Erweiterungen verwendet haben. Ab PHP 5.1 gibt es einen besseren Weg. PHP-Datenobjekte (PDO) bieten Methoden für vorbereitete Anweisungen und die Arbeit mit Objekten, die Sie wesentlich produktiver machen!

CRUD-Generatoren und Frameworks

Der Datenbankcode wiederholt sich, ist aber sehr wichtig, um ihn richtig zu machen. Hier kommen PHP-CRUD-Generatoren und -Frameworks ins Spiel – sie sparen Ihnen Zeit, indem sie all diesen sich wiederholenden Code automatisch generieren, sodass Sie sich auf andere Teile der App konzentrieren können.

Auf CodeCanyon finden Sie CRUD-Generatoren und Frameworks, die Ihnen helfen, Produkte von herausragender Qualität pünktlich zu liefern. (CRUD ist ein Akronym für create, read, update und delete – die grundlegenden Manipulationen für eine Datenbank.)

  • Nützliche PHP-CRUD-Generatoren und Frameworks für PHP9 verfügbar auf CodeCanyonFranc Lucas
  • PHPErstellen Sie schnell eine PHP CRUD-Schnittstelle mit dem PDO Advanced CRUD Generator ToolSajal Soni

Einführung in PDO

PDO – PHP-Datenobjekte – sind eine Datenbankzugriffsschicht, die eine einheitliche Methode für den Zugriff auf mehrere Datenbanken bietet.

Es berücksichtigt keine datenbankspezifische Syntax, kann aber ermöglichen, dass der Prozess des Wechselns von Datenbanken und Plattformen ziemlich schmerzlos ist, indem in vielen Fällen einfach die Verbindungszeichenfolge gewechselt wird.

Dieses Tutorial ist nicht als vollständige Anleitung zu SQL gedacht. Es wurde hauptsächlich für Leute geschrieben, die derzeit mysql verwenden oder mysqli Erweiterung, um ihnen den Sprung zum tragbareren und leistungsfähigeren PDO zu erleichtern.

Wenn es um Datenbankoperationen in PHP geht, bietet PDO viele Vorteile gegenüber der rohen Syntax. Lassen Sie uns schnell einige auflisten:

  • Abstraktionsebene
  • objektorientierte Syntax
  • Unterstützung für vorbereitete Anweisungen
  • bessere Ausnahmebehandlung
  • sichere und wiederverwendbare APIs
  • Unterstützung für alle gängigen Datenbanken

Datenbankunterstützung

Die Erweiterung kann jede Datenbank unterstützen, für die ein PDO-Treiber geschrieben wurde. Zum Zeitpunkt der Erstellung dieses Dokuments sind die folgenden Datenbanktreiber verfügbar:

  • PDO_DBLIB (FreeTDS/Microsoft SQL Server/Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle Call-Schnittstelle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC und win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 und SQLite 2)
  • PDO_4D (D)

Alle diese Treiber sind nicht unbedingt auf Ihrem System verfügbar; So finden Sie schnell heraus, welche Treiber Sie haben:

print_r(PDO::getAvailableDrivers());

Verbinden

Unterschiedliche Datenbanken können leicht unterschiedliche Verbindungsmethoden haben. Unten sehen Sie die Methode zum Herstellen einer Verbindung zu einigen der beliebtesten Datenbanken. Sie werden feststellen, dass die ersten drei bis auf den Datenbanktyp identisch sind – und dann hat SQLite seine eigene Syntax.

versuchen Sie { # MS SQL Server und Sybase mit PDO_DBLIB $DBH =new PDO("mssql:host =$host;dbname=$dbname", $user, $pass); $DBH =new PDO("sybase:host=$host;dbname=$dbname", $user, $pass); # MySQL mit PDO_MYSQL $DBH =new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite-Datenbank $DBH =new PDO("sqlite:my/database/path/database.db");}catch(PDOException $e) { echo $e->getMessage();}

Bitte beachten Sie den Try/Catch-Block. Sie sollten Ihre PDO-Operationen immer in Try/Catch verpacken und den Exception-Mechanismus verwenden – mehr dazu in Kürze. Normalerweise stellen Sie nur eine einzige Verbindung her – es sind mehrere aufgelistet, um Ihnen die Syntax zu zeigen. $DBH steht für „Datenbank-Handle“ und wird in diesem Tutorial verwendet.

Sie können jede Verbindung schließen, indem Sie das Handle auf null setzen.

# Verbindung schließen$DBH =null;

Weitere Informationen zu datenbankspezifischen Optionen und/oder Verbindungszeichenfolgen für andere Datenbanken erhalten Sie unter PHP.net.

Ausnahmen und PDO

PDO kann Ausnahmen verwenden, um Fehler zu behandeln, was bedeutet, dass alles, was Sie mit PDO tun, in einen Try/Catch-Block eingeschlossen werden sollte. Sie können PDO in einen von drei Fehlermodi zwingen, indem Sie das Fehlermodus-Attribut auf Ihr neu erstelltes Datenbank-Handle setzen. Hier ist die Syntax:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

Unabhängig davon, welchen Fehlermodus Sie einstellen, erzeugt ein Verbindungsfehler immer eine Ausnahme, und das Erstellen einer Verbindung sollte immer in einem try/catch-Block enthalten sein.

PDO::ERRMODE_SILENT

Dies ist der Standardfehlermodus. Wenn Sie es in diesem Modus belassen, müssen Sie nach Fehlern suchen, wie Sie es wahrscheinlich gewohnt sind, wenn Sie mysql verwendet haben oder mysqli Erweiterungen. Die anderen beiden Methoden eignen sich besser für die DRY-Programmierung.

PDO::ERRMODE_WARNING

Dieser Modus gibt eine Standard-PHP-Warnung aus und erlaubt dem Programm, die Ausführung fortzusetzen. Es ist nützlich zum Debuggen.

PDO::ERRMODE_EXCEPTION

Dies ist der Modus, den Sie in den meisten Situationen wünschen. Es löst eine Ausnahme aus, sodass Sie Fehler elegant behandeln und Daten verbergen können, die jemandem helfen könnten, Ihr System auszunutzen. Hier ist ein Beispiel für die Nutzung von Ausnahmen:

# mit der Datenbank verbindentry { $DBH =new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); # UH-OH! DELECT statt SELECT eingegeben! $DBH->prepare('DELECT name FROM people');}catch(PDOException $e) { echo "Es tut mir leid, Dave. Ich fürchte, das kann ich nicht."; file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);}

Es gibt einen absichtlichen Fehler in der select-Anweisung; Dies führt zu einer Ausnahme. Die Ausnahme sendet die Einzelheiten des Fehlers an eine Protokolldatei und zeigt dem Benutzer eine freundliche (oder weniger freundliche) Nachricht an.

Einfügen und aktualisieren

Das Einfügen neuer Daten (oder das Aktualisieren vorhandener Daten) ist eine der häufigeren Datenbankoperationen. Bei Verwendung von PHP PDO ist dies normalerweise ein zweistufiger Prozess. Alles, was in diesem Abschnitt behandelt wird, gilt gleichermaßen für das UPDATE und INSERT Operationen.

Hier ist ein Beispiel für die grundlegendste Art der Einfügung:

# STH bedeutet "Statement Handle"$STH =$DBH->prepare("INSERT INTO folks ( first_name ) values ​​( 'Cathy' )");$STH->execute();

Sie können denselben Vorgang auch mit exec() ausführen Methode, mit einem Aufruf weniger. In den meisten Situationen werden Sie die längere Methode verwenden, damit Sie vorbereitete Anweisungen nutzen können. Selbst wenn Sie es nur einmal verwenden, schützt Sie die Verwendung vorbereiteter Anweisungen vor SQL-Injection-Angriffen.

Vorbereitete Erklärungen

Die Verwendung vorbereiteter Anweisungen hilft, Sie vor SQL-Injection zu schützen.

Eine vorbereitete Anweisung ist eine vorkompilierte SQL-Anweisung, die mehrmals ausgeführt werden kann, indem nur die Daten an den Server gesendet werden. Es hat den zusätzlichen Vorteil, dass die in den Platzhaltern verwendeten Daten automatisch vor SQL-Injection-Angriffen geschützt werden.

Sie verwenden eine vorbereitete Anweisung, indem Sie Platzhalter in Ihr SQL einfügen. Hier sind drei Beispiele:eines ohne Platzhalter, eines mit unbenannten Platzhaltern und eines mit benannten Platzhaltern.

# keine Platzhalter - reif für SQL Injection!$STH =$DBH->prepare("INSERT INTO folks (name, addr, city) values ​​($name, $addr, $city)"); # unbenannte Platzhalter$STH =$DBH->prepare("INSERT INTO people (name, address, city) values ​​(?, ?, ?)"); # benannte Platzhalter$STH =$DBH->prepare("INSERT INTO people (name, address, city) values ​​(:name, :addr, :city)");

Sie möchten die erste Methode vermeiden; es ist hier zum vergleich. Die Wahl, benannte oder unbenannte Platzhalter zu verwenden, wirkt sich darauf aus, wie Sie Daten für diese Anweisungen festlegen.

Unbenannte Platzhalter

# jedem Platzhalter Variablen zuweisen, indiziert 1-3$STH->bindParam(1, $name);$STH->bindParam(2, $addr);$STH->bindParam(3, $city); # eine Zeile einfügen$name ="Daniel"$addr ="1 Wicked Way";$city ="Arlington Heights";$STH->execute(); # weitere Zeile mit anderen Werten einfügen$name ="Steve"$addr ="5 Circle Drive";$city ="Schaumburg";$STH->execute();

Hier gibt es zwei Schritte. Zuerst weisen wir den verschiedenen Platzhaltern Variablen zu (Zeile 2–4). Dann weisen wir diesen Platzhaltern Werte zu und führen die Anweisung aus. Um einen weiteren Datensatz zu senden, ändern Sie einfach die Werte dieser Variablen und führen Sie die Anweisung erneut aus.

Erscheint dies etwas unhandlich für Anweisungen mit vielen Parametern? Es ist. Wenn Ihre Daten jedoch in einem Array gespeichert sind, gibt es eine einfache Abkürzung:

# die Daten, die wir einfügen wollen$data =array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); $STH =$DBH->prepare("INSERT INTO people (name, address, city) values ​​(?, ?, ?)");$STH->execute($data);

Ganz einfach!

Die Daten im Array gelten der Reihe nach für die Platzhalter. $data[0] geht in den ersten Platzhalter, $data[1] die zweite usw. Wenn Ihre Array-Indizes jedoch nicht in Ordnung sind, funktioniert dies nicht richtig, und Sie müssen das Array neu indizieren.

Benannte Platzhalter

Sie könnten wahrscheinlich die Syntax erraten, aber hier ist ein Beispiel:

# das erste Argument ist der benannte Platzhaltername - beachten Sie, dass benannte# Platzhalter immer mit einem Doppelpunkt beginnen. $STH->bindParam(':name', $name);

Sie können hier auch eine Verknüpfung verwenden, die jedoch mit assoziativen Arrays funktioniert. Hier ist ein Beispiel:

# die Daten, die wir einfügen wollen$data =array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' ); # die Abkürzung!$STH =$DBH->prepare("INSERT INTO folks (name, address, city) value (:name, :addr, :city)");$STH->execute($data); 

Die Schlüssel Ihres Arrays müssen nicht mit einem Doppelpunkt beginnen, müssen aber ansonsten mit den benannten Platzhaltern übereinstimmen. Wenn Sie ein Array von Arrays haben, können Sie darüber iterieren und einfach execute aufrufen mit jedem Array von Daten.

Ein weiteres nettes Feature von benannten Platzhaltern ist die Möglichkeit, Objekte direkt in Ihre Datenbank einzufügen, vorausgesetzt, die Eigenschaften passen zu den benannten Feldern. Hier ist ein Beispielobjekt und wie Sie Ihre Einfügung durchführen würden:

# eine einfache Objektklasse person { public $name; öffentliche $adr; öffentliche $stadt; function __construct($n,$a,$c) { $this->name =$n; $this->adr =$a; $diese->Stadt =$c; } # etc ...} $cathy =new person('Cathy','9 Dark and Twisty','Cardiff'); # Hier ist der lustige Teil:$STH =$DBH->prepare("INSERT INTO folks (name, address, city) value (:name, :addr, :city)");$STH->execute((array)$ cathy);

Casting des Objekts in ein Array im execute bedeutet, dass die Eigenschaften als Array-Schlüssel behandelt werden.

Daten auswählen

Daten werden über ->fetch() abgerufen , eine Methode Ihres Anweisungs Handles. Bevor Sie fetch aufrufen, teilen Sie PDO am besten mit, wie die Daten abgerufen werden sollen. Sie haben folgende Möglichkeiten:

  • PDO::FETCH_ASSOC : gibt ein Array zurück, das durch den Spaltennamen indiziert ist.
  • PDO::FETCH_BOTH (Standard): gibt ein Array zurück, das sowohl durch den Spaltennamen als auch durch die Nummer indexiert ist.
  • PDO::FETCH_BOUND : weist die Werte Ihrer Spalten den mit ->bindColumn() gesetzten Variablen zu Methode.
  • PDO::FETCH_CLASS : weist die Werte Ihrer Spalten den Eigenschaften der benannten Klasse zu. Es erstellt die Eigenschaften, wenn keine übereinstimmenden Eigenschaften vorhanden sind.
  • PDO::FETCH_INTO : aktualisiert eine vorhandene Instanz der benannten Klasse.
  • PDO::FETCH_LAZY :kombiniert PDO::FETCH_BOTH /PDO::FETCH_OBJ , wodurch die Objektvariablennamen so erstellt werden, wie sie verwendet werden.
  • PDO::FETCH_NUM : gibt ein Array zurück, das durch die Spaltennummer indiziert ist.
  • PDO::FETCH_OBJ : gibt ein anonymes Objekt mit Eigenschaftsnamen zurück, die den Spaltennamen entsprechen.

In Wirklichkeit gibt es drei, die die meisten Situationen abdecken: FETCH_ASSOCFETCH_CLASS und FETCH_OBJ . Um die Abrufmethode festzulegen, wird die folgende Syntax verwendet:

$STH->setFetchMode(PDO::FETCH_ASSOC);

Sie können den Abruftyp auch direkt innerhalb von ->fetch() festlegen Methodenaufruf.

FETCH_ASSOC

Dieser Abruftyp erstellt ein assoziatives Array, das nach Spaltennamen indiziert ist. Dies sollte jedem bekannt sein, der die Erweiterungen mysql/mysqli verwendet hat. Hier ist ein Beispiel für die Auswahl von Daten mit dieser Methode:

# hier die Abkürzung ->query() Methode verwenden, da es keine # Variablenwerte in der select-Anweisung gibt. $STH =$DBH->query('SELECT name, address, city from folks'); # Festlegen des Abrufmodus$STH->setFetchMode(PDO::FETCH_ASSOC); while($row =$STH->fetch()) { echo $row['name'] . "\n"; echo $row['addr'] . "\n"; echo $row['city'] . "\n";}

Die While-Schleife durchläuft die Ergebnismenge Zeile für Zeile, bis sie vollständig ist.

FETCH_OBJ

Dieser Abruftyp erstellt ein Objekt der std-Klasse für jede Zeile abgerufener Daten. Hier ist ein Beispiel:

# Anweisung erstellen$STH =$DBH->query('SELECT name, address, city from folks'); # Festlegen des Abrufmodus$STH->setFetchMode(PDO::FETCH_OBJ); # Ergebnisse anzeigenwhile($row =$STH->fetch()) { echo $row->name . "\n"; echo $row->adr . "\n"; echo $row->city . "\n";}

FETCH_CLASS

Die Eigenschaften Ihres Objekts werden festgelegt, BEVOR der Konstruktor aufgerufen wird. Das ist wichtig.

Mit dieser Abrufmethode können Sie Daten direkt in eine Klasse Ihrer Wahl abrufen. Wenn Sie FETCH_CLASS verwenden , werden die Eigenschaften Ihres Objekts BEFORE festgelegt Der Konstruktor wird aufgerufen. Lesen Sie das noch einmal – es ist wichtig. Wenn keine Eigenschaften vorhanden sind, die mit den Spaltennamen übereinstimmen, werden diese Eigenschaften (als öffentlich) für Sie erstellt.

Das bedeutet, dass, wenn Ihre Daten eine Transformation benötigen, nachdem sie aus der Datenbank kommen, dies automatisch von Ihrem Objekt durchgeführt werden kann, wenn jedes Objekt erstellt wird.

Stellen Sie sich beispielsweise eine Situation vor, in der die Adresse für jeden Datensatz teilweise unkenntlich gemacht werden muss. Wir könnten dies tun, indem wir diese Eigenschaft im Konstruktor bearbeiten. Hier ist ein Beispiel:

class secret_person { public $name; öffentliche $adr; öffentliche $stadt; öffentlich $other_data; function __construct($other ='') { $this->address =preg_replace('/[a-z]/', 'x', $this->address); $this->other_data =$andere; }}

Wenn Daten in diese Klasse abgerufen werden, enthält die Adresse alle Kleinbuchstaben a-z Buchstaben, die durch den Buchstaben x ersetzt wurden . Jetzt ist die Verwendung der Klasse und die Durchführung dieser Datentransformation völlig transparent:

$STH =$DBH->query('SELECT name, address, city from people');$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person'); while($obj =$STH->fetch()) { echo $obj->addr;}

Wenn die Adresse „5 Rosebud“ wäre, würden Sie „5 Rxxxxxx“ als Ausgabe sehen. Natürlich kann es Situationen geben, in denen der Konstruktor aufgerufen werden soll, bevor die Daten zugewiesen werden. Auch dafür ist PDO bestens gerüstet.

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');

Wenn Sie nun das vorherige Beispiel mit diesem Abrufmodus wiederholen (PDO::FETCH_PROPS_LATE ), wird die Adresse nicht verdeckt werden, da der Konstruktor aufgerufen und die Eigenschaften zugewiesen wurden.

Schließlich können Sie bei Bedarf Argumente an den Konstruktor übergeben, wenn Sie Daten mit PDO:

in Objekte holen
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

Wenn Sie für jedes Objekt unterschiedliche Daten an den Konstruktor übergeben müssen, können Sie den Abrufmodus innerhalb von fetch festlegen Methode:

$i =0;while($rowObj =$STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) { // Dinge tun $i++}

Einige andere hilfreiche Methoden

Obwohl dies nicht alles in PDO abdecken soll (es ist eine riesige Erweiterung!), gibt es ein paar weitere Methoden, die Sie kennen sollten, um grundlegende Dinge mit PDO zu tun.

$DBH->lastInsertId();

Die ->lastInsertId() -Methode wird immer für das Datenbank-Handle aufgerufen, nicht für das Anweisungs-Handle, und gibt die automatisch inkrementierte ID der zuletzt von dieser Verbindung eingefügten Zeile zurück.

$DBH->exec('DELETE FROM people WHERE 1');$DBH->exec("SET time_zone ='-8:00'");

Die ->exec() -Methode wird für Vorgänge verwendet, die keine anderen Daten als die betroffenen Zeilen zurückgeben können. Das Obige sind zwei Beispiele für die Verwendung der exec-Methode.

$safe =$DBH->quote($unsafe);

Das ->quote() -Methode setzt Zeichenfolgen in Anführungszeichen, damit sie sicher in Abfragen verwendet werden können. Dies ist Ihr Fallback, wenn Sie keine vorbereiteten Anweisungen verwenden.

$rows_affected =$STH->rowCount();

Die ->rowCount() -Methode gibt eine Ganzzahl zurück, die die Anzahl der Zeilen angibt, die von einer Operation betroffen sind. In mindestens einer bekannten Version von PDO funktionierte die Methode nicht mit ausgewählten Anweisungen. Es funktioniert jedoch ordnungsgemäß in Version PHP 5.1.6 und höher.

Wenn Sie dieses Problem haben und PHP nicht aktualisieren können, können Sie die Anzahl der Zeilen wie folgt ermitteln:

$sql ="SELECT COUNT(*) FROM people";if ($STH =$DBH->query($sql)) { # Überprüfe die Zeilenanzahl if ($STH->fetchColumn()> 0) { # Geben Sie hier ein echtes Select aus, weil es Daten gibt! } else { echo "Keine Zeilen stimmten mit der Abfrage überein."; }}

PHP-CRUD-Generatoren von CodeCanyon

Sie können sich Stunden Zeit sparen, indem Sie einen PHP-CRUD-Generator von CodeCanyon finden und ihn in Ihren Projekten verwenden. Hier sind fünf der beliebtesten Downloads, die Sie sofort verwenden können.

1. Laravel-Mehrzweckanwendung:Sximo 6

Der Sximo 6 Builder basiert auf den beliebtesten Frameworks. Es hat auch ein neues Update für 2021 erhalten, das es so einfach zu bedienen und funktionsreich wie möglich macht. Einige dieser Funktionen umfassen:

  • Verwaltung von Datenbanktabellen
  • Frontend- und Backend-Vorlagen
  • Modul MySQL-Editor
  • Unterstützung für mehrere Bilder und Datei-Upload

Probieren Sie es aus, wenn Sie mit einer CRUD-PHP-Vorlage Zeit sparen möchten.

2. PDO Crud:Formularersteller und Datenbankverwaltung

Hier ist ein weiterer leistungsstarker CRUD-PHP-Generator. Diese PHP-PDO-Codevorlage eignet sich gut für die Datenbankverwaltung. Aber das ist noch nicht alles. Sie können PDO CRUD auch verwenden, um hilfreiche Formulare direkt aus Ihren Datenbanktabellen zu erstellen. Es ist eine nützliche Funktion, die nicht viele andere Optionen haben.

3. Cicool:Seiten-, Formular-, Rest-API und CRUD-Generator

Cicool ist ein weiterer Mehrzweck-Builder, der einen Blick wert ist. Es bietet nicht nur einen CRUD-Builder, sondern auch:

  • Seitenersteller
  • Formularersteller
  • Rest-API-Builder

Zusätzlich zu diesen Funktionen können Sie Cicool auch Erweiterungen hinzufügen und das Design ganz einfach anpassen.

4. PHP-CRUD-Generator

Einfacher Admin-Panel-Builder? Überprüfen. Einfach zu navigierende Oberfläche? Überprüfen. Umfassende Datenbankanalyse? Ein weiterer Scheck. Dieser PHP-CRUD-Generator hat alles, was Sie brauchen, um großartige Dashboards zu erstellen und Ihre Daten zu speichern. Mit verschiedenen Benutzerauthentifizierungs- und Rechteverwaltungsfunktionen ist diese PDO-PHP-Vorlage einen Blick wert.