Wenn Sie PDO verwenden müssen, besteht der erste Schritt darin, den DSN (Datenquellennamen) korrekt zu schreiben. In diesem Artikel wird systematisch die DSN-Syntax, die leicht zu misstrauischen Punkte und Best Practices gängiger Datenbanken herausgestellt und eine Liste von Beispielcodes und Überprüfungen enthält, die direkt angewendet werden können.
DSN : Teilen Sie PDO mit, welchen Treiber (MySQL, PGSQL, SQLite…), welchen Host, welche Bibliothek und andere Verbindungsparameter zu einer Verbindung herstellen sollen.
Ort : Neue PDO ($ DSN, $ userername, $ password, $ option)
Struktur : <Treiber>: <Key> = <wert>;
Fallempfindlichkeit : Treibernamen und Schlüsselnamen sind normalerweise nicht zur Fall, aber der Wert ist unterschiedlich (z. B. Dateipfade).
Base:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'mysql:host=127.0.0.1;port=3306;dbname=app;charset=utf8mb4'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>, [
PDO::</span><span><span class="hljs-variable constant_">ATTR_ERRMODE</span></span><span> => PDO::</span><span><span class="hljs-variable constant_">ERRMODE_EXCEPTION</span></span><span>,
]);
</span></span>Wichtige Punkte und Optionen:
Host : Der Domänenname/der Domänenname/die IP ist verfügbar. Wenn Sie zu Unix Socket gehen, verwenden Sie Unix_Socket =/path/mysql.sock und schreiben Sie nicht erneut Host/Port.
DBNAME : Zieldatenbankname.
CharSet : Es wird dringend empfohlen, UTF8MB4 festzulegen.
Port : Kann weggelassen werden, Standard ist 3306.
SSL : Die neue Version von MySQL/Treiber kann mit der Option PDO :: MySQL_ATTR_SSL_* kombiniert werden (siehe "Sicherheits- und Leistungsoptionen" am Ende des Artikels).
UNIX -Socket -Beispiel:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=app;charset=utf8mb4'</span></span><span>;
</span></span>Sichere Schreibmethode zum Spleißen mit mehreren Parametern (Antisemi-Colon/Sonderzeichen):
<span><span><span class="hljs-variable">$params</span></span><span> = [
</span><span><span class="hljs-string">'host'</span></span><span> => </span><span><span class="hljs-string">'db.internal'</span></span><span>,
</span><span><span class="hljs-string">'port'</span></span><span> => </span><span><span class="hljs-number">3306</span></span><span>,
</span><span><span class="hljs-string">'dbname'</span></span><span> => </span><span><span class="hljs-string">'app'</span></span><span>,
</span><span><span class="hljs-string">'charset'</span></span><span> => </span><span><span class="hljs-string">'utf8mb4'</span></span><span>,
];
</span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'mysql:'</span></span><span> . </span><span><span class="hljs-title function_ invoke__">implode</span></span><span>(</span><span><span class="hljs-string">';'</span></span><span>, </span><span><span class="hljs-title function_ invoke__">array_map</span></span><span>(
fn(</span><span><span class="hljs-variable">$k</span></span><span>,</span><span><span class="hljs-variable">$v</span></span><span>) => </span><span><span class="hljs-variable">$k</span></span><span> . </span><span><span class="hljs-string">'='</span></span><span> . </span><span><span class="hljs-title function_ invoke__">str_replace</span></span><span>(</span><span><span class="hljs-string">';'</span></span><span>, </span><span><span class="hljs-string">'\;'</span></span><span>, (</span><span><span class="hljs-keyword">string</span></span><span>)</span><span><span class="hljs-variable">$v</span></span><span>),
</span><span><span class="hljs-title function_ invoke__">array_keys</span></span><span>(</span><span><span class="hljs-variable">$params</span></span><span>),
</span><span><span class="hljs-variable">$params</span></span><span>
));
</span></span>Base:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'pgsql:host=127.0.0.1;port=5432;dbname=app'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span></span>Schlüsselpunkte:
Der Host kann ein Pfad (UNIX Domain Socket -Verzeichnis, normalerweise /var/run/postgresql ) sein, und der Port kann zu diesem Zeitpunkt weggelassen werden.
Das Zeichensatz wird empfohlen, um festgelegte Namen nach Optionen oder Verbindung auszuführen oder Optionen = '-Client_encoding = Utf8' zu verwenden.
Einige Szenarien bevorzugen die Schreibmethode von Host =/var/run/postgresql .
UNIX -Socket -Beispiel:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">"pgsql:host=/var/run/postgresql;dbname=app"</span></span><span>;
</span></span>Dateidatenbank:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'sqlite:/path/to/database.sqlite'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>);
</span></span>In-Memory-Datenbank:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'sqlite::memory:'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>);
</span></span>Schlüsselpunkte:
Wenn der Pfad Leerzeichen oder Semikolone enthält, wird empfohlen, Sonderzeichen im realen Dateipfad zu vermeiden. Verwenden Sie doppelte Backslashes oder Slash -Pfade unter Windows: C: \\ Data \\ db.sqlite oder c: /data/db.sqlite .
Base:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'sqlsrv:Server=127.0.0.1,1433;Database=app'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span></span>Schlüsselpunkte:
Server kann Host-, Port- oder Hostname \ Instance schreiben.
Es wird empfohlen, die Codierung durch Optionen festzulegen: pdo :: sqlsrv_attr_encoding .
TLS/Verschlüsselung wird normalerweise durch Treiberoptionen weitergegeben (siehe Ende des Artikels).
Genannte Beispiele:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'sqlsrv:Server=WIN-SRV\\SQLEXPRESS;Database=app'</span></span><span>;
</span></span>Base:
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'oci:dbname=//127.0.0.1:1521/ORCL;charset=AL32UTF8'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span></span>Schlüsselpunkte:
DBNAME unterstützt Aliase in // Host: port/service_name oder lokale tnsnames.ora .
Empfohlene Al32UTF8 -Codierung.
<span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'ibm:DRIVER={IBM DB2 ODBC DRIVER};DATABASE=APP;HOSTNAME=127.0.0.1;PORT=50000;PROTOCOL=TCPIP;'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span></span> <span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-string">'firebird:dbname=localhost:/path/to/db.fdb;charset=UTF8'</span></span><span>;
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span></span>Spezifikation: <Treiber>: key = value; key = value , semicolon ist ein separator .
Wenn der Wert ein Semikolon (sehr selten) enthalten kann, wird empfohlen, ihn nicht in den DSN zu füllen, sondern sich auf den vierten Parameter $ -Optionen zu ändern oder durch eine Konfigurationsmethode ohne Semikolon (z. B. Umgebungsvariablenverteilung und dann DSN).
MySQL : Es ist am intuitivsten, charset = utf8mb4 in DSN hinzuzufügen; Legen Sie keine Namen nach der Verbindung ein , um eine Duplizierung zu vermeiden.
PostgreSQL : Es wird empfohlen, in Optionen einzustellen --client_encoding = utf8 oder verwenden Sie SET client_encoding nach "utf8" nach der Verbindung.
SQL Server : Setzen Sie die Option PDO :: SQLSRV_ATTTR_ECODING (wie SQLSRV_Enoding_UTF8 ).
Verwenden Sie nicht UNIX_SOCKET und HOST/Port in MySQL.
Der Socket von PostgreSQL wird implementiert, indem der Host auf ein Verzeichnis hingewiesen wird.
Dateipfade wie SQLite werden empfohlen, um doppelte Backslashes oder Slashes unter Windows zu verwenden: C: \\ Path \\ db.sqlite oder c: /pat/db.sqlite .
Schärfen Sie das Kontokennwort nicht in das Lagerhaus fest:
.Env : db_dsn = mysql: host =…; dbname =…; charset = utf8mb4
Laufzeit: $ pdo = new pdo (Getenv ('db_dsn'), Getenv ('db_user'), Getenv ('db_pass'));
<span><span><span class="hljs-variable">$opts</span></span><span> = [
PDO::</span><span><span class="hljs-variable constant_">ATTR_ERRMODE</span></span><span> => PDO::</span><span><span class="hljs-variable constant_">ERRMODE_EXCEPTION</span></span><span>, </span><span><span class="hljs-comment">// Wirf eine Ausnahme,Einfach zu lokalisieren</span></span><span>
PDO::</span><span><span class="hljs-variable constant_">ATTR_DEFAULT_FETCH_MODE</span></span><span> => PDO::</span><span><span class="hljs-variable constant_">FETCH_ASSOC</span></span><span>, </span><span><span class="hljs-comment">// Gibt das assoziative Array standardmäßig zurück</span></span><span>
PDO::</span><span><span class="hljs-variable constant_">ATTR_EMULATE_PREPARES</span></span><span> => </span><span><span class="hljs-literal">false</span></span><span>, </span><span><span class="hljs-comment">// Lassen Sie den Fahrer native Vorverarbeitung verwenden(Sicherheit/Stabilere Leistung)</span></span><span>
];
</span><span><span class="hljs-comment">// MySQL SSL Beispiel(Wenn Fahrerunterstützung):</span></span><span>
</span><span><span class="hljs-variable">$opts</span></span><span>[PDO::</span><span><span class="hljs-variable constant_">MYSQL_ATTR_SSL_CA</span></span><span>] = </span><span><span class="hljs-string">'/etc/ssl/certs/ca.pem'</span></span><span>;
</span><span><span class="hljs-comment">// $opts[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; // Wenn Sie die Überprüfung überspringen müssen(Nicht empfohlen)</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-variable">$dsn</span></span><span>, </span><span><span class="hljs-variable">$user</span></span><span>, </span><span><span class="hljs-variable">$pass</span></span><span>, </span><span><span class="hljs-variable">$opts</span></span><span>);
</span></span>Hinweis:
Vorverarbeitungsanweisungen können mit dem kombiniert werden ? oder genannte Platzhalter, um die SQL -Injektion zu vermeiden.
Die Produktionsumgebung muss TLS/SSL aktivieren (erfordert eine gemeinsame Unterstützung zwischen Server und Treiber).
<span><span><span class="hljs-meta"><?php</span></span><span>
</span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">build_mysql_dsn</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-keyword">array</span></span></span><span> </span><span><span class="hljs-variable">$cfg</span></span><span>): </span><span><span class="hljs-title">string</span></span><span> {
</span><span><span class="hljs-comment">// Unterstützung host/port oder unix_socket,Filterer leere Werte automatisch filtern</span></span><span>
</span><span><span class="hljs-variable">$parts</span></span><span> = [];
</span><span><span class="hljs-variable">$parts</span></span><span>[] = </span><span><span class="hljs-keyword">isset</span></span><span>(</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'unix_socket'</span></span><span>])
? </span><span><span class="hljs-string">'unix_socket='</span></span><span> . </span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'unix_socket'</span></span><span>]
: </span><span><span class="hljs-string">'host='</span></span><span> . (</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'host'</span></span><span>] ?? </span><span><span class="hljs-string">'127.0.0.1'</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-keyword">empty</span></span><span>(</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'unix_socket'</span></span><span>]) && !</span><span><span class="hljs-keyword">empty</span></span><span>(</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'port'</span></span><span>])) {
</span><span><span class="hljs-variable">$parts</span></span><span>[] = </span><span><span class="hljs-string">'port='</span></span><span> . (</span><span><span class="hljs-keyword">int</span></span><span>)</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'port'</span></span><span>];
}
</span><span><span class="hljs-keyword">if</span></span><span> (!</span><span><span class="hljs-keyword">empty</span></span><span>(</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'dbname'</span></span><span>])) {
</span><span><span class="hljs-variable">$parts</span></span><span>[] = </span><span><span class="hljs-string">'dbname='</span></span><span> . </span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'dbname'</span></span><span>];
}
</span><span><span class="hljs-variable">$parts</span></span><span>[] = </span><span><span class="hljs-string">'charset='</span></span><span> . (</span><span><span class="hljs-variable">$cfg</span></span><span>[</span><span><span class="hljs-string">'charset'</span></span><span>] ?? </span><span><span class="hljs-string">'utf8mb4'</span></span><span>);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-string">'mysql:'</span></span><span> . </span><span><span class="hljs-title function_ invoke__">implode</span></span><span>(</span><span><span class="hljs-string">';'</span></span><span>, </span><span><span class="hljs-variable">$parts</span></span><span>);
}
</span><span><span class="hljs-comment">// Verwendung</span></span><span>
</span><span><span class="hljs-variable">$dsn</span></span><span> = </span><span><span class="hljs-title function_ invoke__">build_mysql_dsn</span></span><span>([
</span><span><span class="hljs-string">'host'</span></span><span> => </span><span><span class="hljs-string">'db.internal'</span></span><span>,
</span><span><span class="hljs-string">'port'</span></span><span> => </span><span><span class="hljs-number">3306</span></span><span>,
</span><span><span class="hljs-string">'dbname'</span></span><span> => </span><span><span class="hljs-string">'app'</span></span><span>,
</span><span><span class="hljs-string">'charset'</span></span><span> => </span><span><span class="hljs-string">'utf8mb4'</span></span><span>,
]);
</span><span><span class="hljs-comment">// new PDO($dsn, $user, $pass, $opts);</span></span><span>
</span></span>Der Treiber ist nicht installiert : Der Treiber kann nicht finden → Überprüfen Sie, ob es in PHP -M pdo_mysql / pdo_pgsql usw. gibt.
Host- oder Port -Fehler : SQLState [Hy000] [2002] (MySQL) → Überprüfen Sie den Host/Port oder unix_socket .
Die Datenbank existiert nicht : Unbekannte Datenbank 'xxx' → DBNAME beheben oder zuerst die Bibliothek erstellen.
Codierungsproblem : Der verstümmelte Code wird angezeigt. → Bestätigen Sie, dass die Zeichensätze in der DSN/Option konsistent sind (MySQL verwendet charSet = utf8mb4 , PG setzt Client_encoding = utf8 ).
TLS/Zertifikat : SSL -Handshake fehlgeschlagen → Überprüfen Sie den CA -Pfad, unabhängig davon, ob TLS auf dem Server aktiviert ist und das Zertifikat mit dem Domänennamen übereinstimmt.
Unzureichende Berechtigungen : Erlaubnis verweigert oder zugänglich verweigert → Benutzername/Kennwort überprüfen, Benutzerberechtigungen in der Zielbibliothek.
<span><span>MySQL
mysql:host=HOST;port=3306;dbname=DB;charset=utf8mb4
mysql:unix_socket=/path/mysql.sock;dbname=DB;charset=utf8mb4
PostgreSQL
pgsql:host=HOST;port=5432;dbname=DB
pgsql:host=/var/run/postgresql;dbname=DB
SQLite
sqlite:/absolute/path/to/db.sqlite
sqlite::memory:
SQL Server
sqlsrv:Server=HOST,1433;Database=DB
sqlsrv:Server=HOST\INSTANCE;Database=DB
Oracle
oci:dbname=//HOST:1521/SERVICE;charset=AL32UTF8
Db2
ibm:DRIVER={IBM DB2 ODBC DRIVER};DATABASE=DB;HOSTNAME=HOST;PORT=50000;PROTOCOL=TCPIP;
Firebird
firebird:dbname=HOST:/path/to/db.fdb;charset=UTF8
</span></span>
Verwandte Tags:
PDO