COMP3512
winter 2024
lec-php-08
Buh-bye, January


About that midterm
- You get one 3"x5" index card you can use as a reference guide.
- I have some if you don't have any.
- No MCQ. Short answer, fill in the blanks, and code writing.
- Covers all topics from the start of semester up to and including today.
- Look up PHP's explode() . Almost as good a name as die().
RECALL

Let's do a PDO word web.
Project Requirements
are up
let's talk about these things today:
◉ Let's finish our example from last lecture.
◉ What's a prepared statement - and why should I use them?
◉ Can we clean this up at all?
DB
Let's finish our example from last lecture.
We were making a page that displays all cheeses that are out of stock in the Banff cheese store.
Example, continued.
1-stock
What's a prepared statement - and why should you use them?
Let's build another page.
We want to show all the names of cheeses of a given classification code at a given store that are in stock.
The classification and store ids could come in via a query string or a form, perhaps.
For example, if we were given the store id 1 (Calgary) and classification code "B" , then we'd want to display "Stilton" and "Gorgonzola".
Bringing in outside data.
2-stock-with-outside-data
Then one day, your co-worker shows you this comic.

...and you begin to sweat.
First, you make a dummy database lab_rat with a dummy table.
Then, in your database admin tool of choice, you try out this query...
USE lab_rat;
SELECT cheese.name
FROM cheese
INNER JOIN
inventory ON (cheese.id = cheese_id)
INNER JOIN
classification cl ON (cl.id = classification_id)
WHERE store_id = 1
AND code = 'B'; DROP TABLE cheese; --
AND stock_level > 0
ORDER BY 1...and your heart sinks.
ruh roh
Shaking, you then try THIS query...
USE lab_rat;
SELECT cheese.name
FROM cheese
INNER JOIN
inventory ON (cheese.id = cheese_id)
INNER JOIN
classification cl ON (cl.id = classification_id)
WHERE store_id = 1
AND code = 'B'; DROP DATABSE lab_rat; --
AND stock_level > 0
ORDER BY 1...and you start looking at job listings.
oh dear
Then you go into your code an try this...
Uh-oh.
2-stock-with-outside-data/uh-oh.php
Never trust outside data. Never.
But we NEED outside data for any useful system!
What can we do?
Solution: Prepared Statements
Prepared statements FTW.
2-stock-with-outside-data/whew.php


BRAIN BREAK
Can we clean this up at all?
As it stands, we've got a dumpster fire here.
<?php
$dsn = "mysql:host=127.0.0.1;port=3306;dbname=cheese_db;charset=utf8mb4";
try {
$pdo = new PDO($dsn, "root", "mariadb", [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
} catch (PDOException $e) {
die($e->getMessage());
}
$query = <<<QUERY
SELECT ch.name AS cheese
FROM cheese AS ch
QUERY;
$results = $pdo->query($query);
$pdo = null;
?>
<ul>
<?php foreach ($results as $result) : ?>
<li><?= $result['cheese'] ?> </li>
<?php endforeach ?>
</ul>➀ connect & handle errors
➁ run a query
➃ use results
➂ free resources & close connection
Oh crud - I didn't talk about ➂, did I?
Wet cleanup on aisle 4.
3-cleanup
Having these queries sitting "raw" in our controllers has good points and bad points.
We could make some helper functions that name what we're trying to do with a given query, and group them together in one file.
We could even take that a step further, by making some sort of query helper class....
...which you could take even further by bringing in some inheritance.
lec-php-08
By Jordan Pratt
lec-php-08
prepared statements | our DB library
- 160