Database Connectivity (MySQLi/PDO)
Master database interactions in PHP. Learn prepared statements, PDO bindings, transaction safety, and performance optimization.
Downloaded from PrepIQ (https://prepiq.online)
Q1. What is the difference between MySQLi and PDO in PHP?
Both are database extensions for connecting PHP to databases, but they differ in scope and features.
| Feature | MySQLi | PDO |
|---|---|---|
| Database support | MySQL only | 12+ databases (MySQL, PostgreSQL, SQLite, etc.) |
| API style | Procedural and OOP | OOP only |
| Prepared statements | Yes, but more verbose | Yes, cleaner named parameters |
| Named parameters | No | Yes (e.g. :name) |
PDO is generally preferred for new projects due to database portability and cleaner syntax.
Q2. How do you connect to a MySQL database using PDO?
Create a new PDO instance with a DSN (Data Source Name), username, password, and options. Always wrap it in try-catch since PDO throws exceptions on connection failure.
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=mydb;charset=utf8mb4',
'username',
'password',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
die('Connection failed: ' . $e->getMessage());
}Setting ERRMODE_EXCEPTION ensures database errors throw catchable exceptions instead of silent failures.
Q3. What are prepared statements and why are they important?
Prepared statements separate SQL logic from data, so user input is never treated as executable SQL. This is the primary defense against SQL injection.
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $userInput]);
$user = $stmt->fetch();1. Prepare SQL template with placeholders → 2. Database compiles the query plan → 3. Bind actual values → 4. Execute with values treated strictly as data, never code
Without prepared statements, concatenating user input directly into SQL strings allows attackers to inject malicious SQL.
Q4. How do you handle transactions in PDO?
Transactions ensure a group of database operations either all succeed or all fail together, maintaining data consistency.
try {
$pdo->beginTransaction();
$pdo->prepare('UPDATE accounts SET balance = balance - ? WHERE id = ?')
->execute([100, $fromId]);
$pdo->prepare('UPDATE accounts SET balance = balance + ? WHERE id = ?')
->execute([100, $toId]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}| Method | Purpose |
|---|---|
| beginTransaction() | Starts a transaction |
| commit() | Saves all changes permanently |
| rollBack() | Undoes all changes since begin |
Q5. What is the difference between bindParam() and bindValue() in PDO?
| Aspect | bindParam() | bindValue() |
|---|---|---|
| Binding type | By reference | By value |
| When value is read | At execute() time | Immediately when called |
| Use case | Variable may change before execute | Value is fixed at bind time |
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$id = 5;
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$id = 10;
$stmt->execute();
// Uses 10, because bindParam reads at execute time
Q6. How do you fetch data using PDO in different formats?
PDO supports several fetch styles controlled by PDO::FETCH_* constants.
| Fetch mode | Returns |
|---|---|
| PDO::FETCH_ASSOC | Associative array with column names as keys |
| PDO::FETCH_OBJ | Anonymous stdClass object |
| PDO::FETCH_NUM | Array indexed by column position |
| PDO::FETCH_CLASS | Instance of a specified class |
$stmt = $pdo->query('SELECT * FROM users');
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $user) {
echo $user['name'];
}
Q7. How does MySQLi handle prepared statements differently from PDO?
MySQLi uses positional placeholders (?) with a type string for binding, while PDO supports both positional and named placeholders.
$stmt = $mysqli->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->bind_param('si', $email, $status);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}| Aspect | MySQLi | PDO |
|---|---|---|
| Placeholder types | ? only | ? and :name |
| Type declaration | Required (s, i, d, b string) | Optional, auto-detected |
Q8. How do you prevent SQL injection in PHP database queries?
SQL injection happens when untrusted input is concatenated directly into a SQL query, letting attackers alter query logic.
$sql = "SELECT * FROM users WHERE email = '$email'";An input like
' OR '1'='1 bypasses the WHERE clause entirely.Safe:
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);| Practice | Why it helps |
|---|---|
| Prepared statements | Separates code from data |
| Input validation | Rejects malformed input early |
| Least privilege DB user | Limits damage if breached |
Q9. How do you handle database connection errors gracefully?
Set PDO to throw exceptions, catch them, log details for debugging, and show a generic message to users without exposing sensitive info.
try {
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
} catch (PDOException $e) {
error_log('DB connection failed: ' . $e->getMessage());
http_response_code(500);
die('A database error occurred. Please try again later.');
}Never echo raw exception messages to end users in production - they can reveal database structure, credentials, or file paths to attackers.
Q10. What is connection pooling and does PHP support it natively?
Connection pooling reuses a set of open database connections across requests instead of opening/closing one per request, reducing overhead.
| Aspect | Detail |
|---|---|
| Native PHP support | No - traditional PHP-FPM creates a new connection per request |
| Persistent connections | PDO::ATTR_PERSISTENT can reuse connections, but has caveats |
| Common solutions | ProxySQL, MySQL Router, application-level pooling in long-running processes (Swoole, RoadRunner) |
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_PERSISTENT => true
]);Persistent connections can cause issues with transaction state leaking between requests, so they should be used carefully and tested thoroughly.
Database Connectivity (MySQLi/PDO)
Master database interactions in PHP. Learn prepared statements, PDO bindings, transaction safety, and performance optimization.
What is the difference between MySQLi and PDO in PHP?
Both are database extensions for connecting PHP to databases, but they differ in scope and features.FeatureMyS...
How do you connect to a MySQL database using PDO?
Create a new PDO instance with a DSN (Data Source Name), username, password, and options. Always wrap it in tr...
What are prepared statements and why are they important?
Prepared statements separate SQL logic from data, so user input is never treated as executable SQL. This is th...
How do you handle transactions in PDO?
Transactions ensure a group of database operations either all succeed or all fail together, maintaining data c...
What is the difference between bindParam() and bindValue() in PDO?
AspectbindParam()bindValue()Binding typeBy referenceBy valueWhen value is readAt execute() timeImmediately whe...
How do you fetch data using PDO in different formats?
PDO supports several fetch styles controlled by PDO::FETCH_* constants.Fetch modeReturnsPDO::FETCH_ASSOCAssoci...
How does MySQLi handle prepared statements differently from PDO?
MySQLi uses positional placeholders (?) with a type string for binding, while PDO supports both positional and...
How do you prevent SQL injection in PHP database queries?
SQL injection happens when untrusted input is concatenated directly into a SQL query, letting attackers alter...
How do you handle database connection errors gracefully?
Set PDO to throw exceptions, catch them, log details for debugging, and show a generic message to users withou...
What is connection pooling and does PHP support it natively?
Connection pooling reuses a set of open database connections across requests instead of opening/closing one pe...