Last updated: August 25, 2026.
PHP provides two supported APIs for working with MySQL: PDO and MySQLi. This guide starts with PDO and then shows MySQLi as an alternative.
Create a small example database
This schema gives the PHP examples something to query:
CREATE DATABASE examples CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE examples;
CREATE TABLE cars (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
model VARCHAR(80) NOT NULL,
model_year SMALLINT UNSIGNED NOT NULL
);
INSERT INTO cars (model, model_year) VALUES
('Mercedes', 2000), ('BMW', 2004), ('Audi', 2001);Connect to MySQL with PDO
PDO provides a consistent database interface and supports prepared statements. Store real credentials outside the public web directory—environment variables are used here for clarity.
<?php
$host = getenv('DB_HOST') ?: 'localhost';
$dbName = getenv('DB_NAME') ?: 'examples';
$user = getenv('DB_USER');
$password = getenv('DB_PASSWORD');
$dsn = "mysql:host={$host};dbname={$dbName};charset=utf8mb4";
$pdo = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);utf8mb4 supports the full Unicode range. Exception mode makes failures explicit, and disabling emulated prepares requests native prepared statements.
Run a prepared query
Never concatenate untrusted input into SQL. Use placeholders and pass values separately:
<?php
$minimumYear = 2000;
$stmt = $pdo->prepare(
'SELECT id, model, model_year
FROM cars
WHERE model_year >= :minimum_year
ORDER BY model_year DESC'
);
$stmt->execute(['minimum_year' => $minimumYear]);
foreach ($stmt->fetchAll() as $car) {
printf("%s (%d)\n", $car['model'], $car['model_year']);
}Prepared statements protect data values. Table names, column names, and SQL keywords cannot be placeholders; choose those from an application-controlled allowlist.
MySQLi alternative
MySQLi is also a current, supported API:
<?php
$mysqli = new mysqli('localhost', $user, $password, 'examples');
$mysqli->set_charset('utf8mb4');
$stmt = $mysqli->prepare(
'SELECT model, model_year FROM cars WHERE model_year >= ?'
);
$stmt->bind_param('i', $minimumYear);
$stmt->execute();
$cars = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);Connection and deployment checklist
- Give the application a dedicated MySQL account with only required permissions.
- Keep passwords in environment variables or a protected secret store.
- Use
utf8mb4on the connection, database, and tables. - Use prepared statements for values from users or external systems.
- Log technical errors privately; show visitors a generic error.
- Use TLS when PHP and MySQL communicate across a network.
See the official PHP documentation for PDO connections and prepared statements.