Working With Databases
Every example so far has worked with data that disappears the moment the script finishes. Real applications store data persistently in a database. This chapter introduces PDO (PHP Data Objects) — PHP's standard way of talking to a database — and CRUD: Create, Read, Update, Delete, the four operations behind almost every data-driven feature.
Connecting With PDO
A PDO connection failure throws a PDOException — exactly the exception handling from Chapter 3, applied immediately to something genuinely likely to fail in the real world (wrong credentials, database server down). ERRMODE_EXCEPTION makes every later database error throw an exception too, rather than failing silently.
The SQL Injection Problem
Prepared Statements — The Fix
:username is a placeholder — the actual value is sent to the database completely separately from the SQL text itself, in a second step (execute()). The database treats the placeholder's value strictly as data, never as part of the SQL command's structure — meaning the attacker's text from above could never be reinterpreted as part of the query's logic. This single habit eliminates SQL injection entirely.
CRUD — The Four Core Operations
Create — INSERT
Read — SELECT
Update — UPDATE
Delete — DELETE
WHERE id = :id condition on an UPDATE or DELETE statement is a genuinely common, genuinely serious mistake — it silently applies the change to the entire table rather than the one row intended. Always double-check a WHERE clause is present before running either statement against a real database.
fetchAll() Fetch Modes
By default, PDO returns rows as both numeric AND associative keys combined — usually more than needed. Setting the fetch mode once after connecting keeps results clean and predictable:
Coding Challenges
Write the PDO connection code for a database called "blog_db" on localhost, wrapped in a try/catch that dies with a friendly message on failure. Set both ERRMODE_EXCEPTION and FETCH_ASSOC as attributes.
📄 View solutionAssuming a "products" table with columns id, name, and price, write prepared statements (with placeholders) for: inserting a new product, selecting all products with a price above a given value, and updating a specific product's price by id.
📄 View solutionWrite a function deleteProductById($pdo, $id) that uses a prepared DELETE statement, wrapped in a try/catch for PDOException, echoing a success or failure message. Explain in a comment why this function would be unsafe if $id were inserted directly into the SQL string instead of used as a placeholder.
Chapter 4 Quick Reference
- new PDO("mysql:host=...;dbname=...", $user, $pass) — connect; wrap in try/catch for PDOException
- ATTR_ERRMODE / ERRMODE_EXCEPTION — makes database errors throw exceptions instead of failing silently
- Never concatenate user input into SQL strings — this is SQL injection, a serious vulnerability
- prepare() + execute([...]) — prepared statements with named (:placeholder) parameters fix this entirely
- CRUD: INSERT (Create), SELECT (Read), UPDATE, DELETE
- fetch() / fetchAll() — one row / all rows, as associative arrays with FETCH_ASSOC set
- lastInsertId() — gets the auto-increment ID of a just-inserted row
- Always include a WHERE clause on UPDATE/DELETE, or risk affecting every row
- Next chapter: sessions and cookies — login systems, authentication basics