PDO Connect

La Lakshmi Priya Updated 04 Nov 2026
5 min read ·Lesson 227 of 229

PDO Connect Connecting With PDO In simple terms: To use a database through PDO, you create a PDO object. You tell it which database to use (type, server, database name, character set), who you are (username and password), and how it should behave (report errors as exceptions, return rows as associative arrays, and so on).

Technically: The PDO constructor takes a DSN (Data Source Name) string, a username, a password, and an array of driver options. The DSN starts with the driver name followed by driver-specific parameters. If the connection fails, the constructor throws a PDOException.

new PDO(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null) The MySQL DSN mysql:host=127.0.0.1;port=3306;dbname=gocourse_shop;charset=utf8mb4 Part Meaning mysql: Use the pdo_mysql driver host=127.0.0.1 Server address (or a hostname, Docker service name, etc.) port=3306 Port (3306 is the default and may be omitted) dbname=gocourse_shop Database to use charset=utf8mb4 Connection character set — always set it, so all languages and emoji work unix_socket=/path/mysql.sock Alternative to host for local socket connections DSNs for other databases look different: pgsql:host=localhost;dbname=shop, sqlite:/path/to/database.sqlite, sqlite::memory:.

A Recommended Connection <?php $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=gocourse_shop;charset=utf8mb4';

$pdo = new PDO($dsn, 'gocourse_app', 'change-this-app-password', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]);

echo "Driver: " . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . "\n"; echo "Server version: " . $pdo->getAttribute(PDO::ATTR_SERVER_VERSION) . "\n"; Output (versions depend on your server) Driver: mysql Server version: 8.4.6 The Options Explained Option Value Why PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION Throw PDOException on errors. This is the default since PHP 8.0; setting it explicitly documents the intention PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC Return rows as associative arrays. The default, FETCH_BOTH, returns every value twice (by name and by number) PDO::ATTR_EMULATE_PREPARES false Use MySQL's real prepared statements instead of PDO's client-side emulation (see below) Emulated vs Native Prepared Statements For MySQL, PDO emulates prepared statements by default: it inserts the escaped values into the SQL itself before sending it. Setting ATTR_EMULATE_PREPARES to false makes MySQL prepare the statement on the server and receive the values separately.

Emulated (default) Native (false) Safety Safe when the connection charset is set in the DSN Safe; values never become part of the SQL Syntax errors detected At execute() At prepare() LIMIT ? with string values Fails (LIMIT '2') Use PDO::PARAM_INT in both modes Same named placeholder used twice Allowed Not allowed Both are secure when used correctly. Many projects choose native prepares for stricter, more predictable behavior.

Handling Connection Failures <?php try { $pdo = new PDO( 'mysql:host=127.0.0.1;dbname=gocourse_shop;charset=utf8mb4', 'gocourse_app', 'wrong-password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] ); } catch (PDOException $e) { error_log('Database connection failed: ' . $e->getMessage()); http_response_code(503); echo "The service is temporarily unavailable. Please try again later.\n"; } Output (for the visitor) The service is temporarily unavailable. Please try again later. Logged Message Database connection failed: SQLSTATE[HY000] [1045] Access denied for user 'gocourse_app'@'localhost' (using password: YES) Never display the exception message to users — it reveals the host, the username, and the database. In PHP 8.2+, the password parameter of the PDO constructor is marked #[\SensitiveParameter], so it is hidden in stack traces; older versions could leak it into logs through uncaught exception traces.

Configuration From the Environment <?php // config/database.php return [ 'dsn' => sprintf( 'mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', getenv('DB_HOST') ?: '127.0.0.1', (int) (getenv('DB_PORT') ?: 3306), getenv('DB_DATABASE') ?: 'gocourse_shop' ), 'username' => getenv('DB_USERNAME') ?: 'gocourse_app', 'password' => getenv('DB_PASSWORD') ?: '', ]; Credentials come from environment variables (see $_ENV), never from code committed to version control.

A Reusable Connection Function <?php // src/pdo.php function pdo(): PDO { static $pdo = null;

if ($pdo === null) { $config = require DIR . '/../config/database.php';

$pdo = new PDO($config['dsn'], $config['username'], $config['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); }

return $pdo; } <?php require DIR . '/src/pdo.php';

$count = pdo()->query('SELECT COUNT(*) FROM products')->fetchColumn(); echo "Products: $count\n"; Output Products: 5 The connection is created once per request and reused. The following PDO lessons use this pdo() helper. In frameworks, a dependency injection container creates the connection and passes it to the classes that need it.

PHP 8.4: Driver-Specific Connections PHP 8.4 introduced driver-specific subclasses and a factory method:

<?php $pdo = PDO::connect('mysql:host=127.0.0.1;dbname=gocourse_shop;charset=utf8mb4', 'gocourse_app', getenv('DB_PASSWORD'));

var_dump($pdo instanceof Pdo\Mysql); // bool(true) PDO::connect() returns an instance of the matching subclass (Pdo\Mysql, Pdo\Pgsql, Pdo\Sqlite, …), which also behaves as a normal PDO object. Driver-specific constants are available on these classes, such as Pdo\Mysql::ATTR_SSL_CA; the older names on the PDO class (PDO::MYSQL_ATTR_SSL_CA) still exist for compatibility.

Secure Connections to Remote Servers For managed cloud databases, encrypt the connection with TLS and verify the server certificate:

<?php $pdo = new PDO($dsn, $username, $password, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, Pdo\Mysql::ATTR_SSL_CA => '/etc/ssl/certs/db-ca.pem', // PHP 8.4+ // PDO::MYSQL_ATTR_SSL_CA => '/etc/ssl/certs/db-ca.pem', // older PHP versions ]); Persistent Connections PDO::ATTR_PERSISTENT => true keeps connections open between requests within the same PHP-FPM worker. It saves connection time, but leftover state (open transactions, locks, session variables) can leak into the next request, and many idle connections may hit the server's connection limit. Use it only after measuring that connection time is a real bottleneck.

Common Mistakes Missing charset=utf8mb4 in the DSN Effect: Garbled non-English text; with emulated prepares, also weaker escaping.

Fix: Always include the charset in the DSN.

Leaving the Default Fetch Mode Effect: Every row contains each value twice (FETCH_BOTH).

Fix: Set PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC.

Showing Connection Errors Effect: Sensitive configuration details are exposed.

Fix: Log the message; show a generic error page.

Connecting Repeatedly Effect: Slow requests and exhausted connection limits.

Fix: Create one connection per request and reuse it.

Best Practices Use a DSN with host, database name, and charset=utf8mb4. Set error mode, default fetch mode, and prepared-statement emulation explicitly. Load credentials from the environment and use a least-privilege database user. Catch connection exceptions, log details, and show users a generic message. Reuse a single connection through a helper or a DI container. Official reference: https://www.php.net/manual/en/pdo.connections.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings Function Arguments PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer PHP Form Handling PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro PHP Class Constants Encryption with Sodium Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS What Is `$_SERVER` ? $_REQUEST $_POST $_GET $_FILES $_COOKIE PHP Type Juggling MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes
Ask about this post
AI Ask about this post

Ask questions about PDO Connect and get answers drawn from it.

Signed-in readers only.