Challenge 3 — Solution Task: Write 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. prepare("DELETE FROM products WHERE id = :id"); $stmt->execute(['id' => $id]); echo "Product $id deleted successfully."; } catch (PDOException $e) { echo "Failed to delete product $id."; } } deleteProductById($pdo, 5); // Why this would be unsafe as raw concatenation instead: // // "DELETE FROM products WHERE id = " . $id // // Even though $id is type-hinted as int here (which already limits // the damage in this specific function), the general problem with // concatenating ANY value - even one that looks numeric - directly // into SQL text is that the database can no longer tell the // difference between "this is data" and "this is part of the SQL // command's own structure." If $id ever came from unchecked user // input without the "int" type hint enforcing it, a value like // "5 OR 1=1" concatenated directly in would change the statement // into "DELETE FROM products WHERE id = 5 OR 1=1" - which deletes // every single row in the table, not just product 5. Using // :id as a placeholder and passing the value through execute() // keeps it strictly as data no matter what it contains. ?> Output: Product 5 deleted successfully. Notes: - The try/catch wraps only the delete operation itself, so a genuine database error (e.g. a foreign key constraint blocking the delete) is caught and reported as a friendly failure message rather than crashing the whole script. - PHP's own "int $id" type hint on the function parameter already blocks a lot of malicious string input before it ever reaches the SQL - but the placeholder is still what actually prevents SQL injection at the database level, and is the technique that matters for any value that isn't already guaranteed to be a safe type. - This mirrors the chapter's own core lesson: the database treats a placeholder's value strictly as data, never as SQL structure, regardless of what that value contains.