Each snippet below has a bug. Predict what goes wrong, then check the solution. Real debugging is the same: predict, run, compare.
Bug 1: the missing first item
<?php
$items = ["pen", "book", "bag"];
for ($i = 1; $i < count($items); $i++) {
echo $items[$i] . " ";
}
What is printed, and what was intended?
Show the answer
It prints book bag. The loop starts at 1, but array positions start at 0. Fix: $i = 0, or use foreach ($items as $item).
<?php
foreach (["pen", "book", "bag"] as $item) {
echo $item . " ";
}
pen book bag
Bug 2: “Not found”
<?php
$email = "ana@example.com";
if (strpos($email, "ana") == false) {
echo "Not found";
} else {
echo "Found";
}
Show the answer
strpos() returns 0 (the position), and 0 == false is true. Use ===, or str_contains().
<?php
$email = "ana@example.com";
echo str_contains($email, "ana") ? "Found" : "Not found";
Found
Bug 3: the last item changes
<?php
$list = [1, 2, 3];
foreach ($list as &$v) {
}
foreach ($list as $v) {
}
echo implode(",", $list);
Show the answer
The output is 1,2,2. After the first loop, $v is still a reference to the last element, so the second loop writes each value into it. Fix: unset($v); after the first loop, or avoid references.
<?php
$list = [1, 2, 3];
foreach ($list as &$v) {
}
unset($v);
foreach ($list as $v) {
}
echo implode(",", $list);
1,2,3
Bug 4: the total is always 0
<?php
$total = 0;
function addToTotal(int $amount): void
{
$total += $amount;
}
addToTotal(5);
addToTotal(10);
echo $total;
Show the answer
The function works on its own local $total (and PHP warns about an undefined variable). Return the new value instead:
<?php
function addToTotal(int $total, int $amount): int
{
return $total + $amount;
}
$total = 0;
$total = addToTotal($total, 5);
$total = addToTotal($total, 10);
echo $total;
15
Bug 5: the greeting shows markup
<?php
$name = $_GET["name"] ?? "guest";
echo "<h1>Hello, $name</h1>";
What is wrong with it?
Show the answer
XSS. ?name=<script>... runs script in the visitor’s browser. Escape output:
<?php
$name = '<script>alert(1)</script>';
echo "<h1>Hello, " . htmlspecialchars($name, ENT_QUOTES, "UTF-8") . "</h1>";
<h1>Hello, <script>alert(1)</script></h1>
Bug 6: the price is wrong
<?php
$price = "19.99";
$quantity = "3";
echo $price * $quantity . " " . ($price * $quantity == 59.97 ? "exact" : "not exact");
What does it print, and why is it risky?
Show the answer
It prints 59.97 not exact. Floating-point numbers are approximate, so 19.99 * 3 is not exactly 59.97. Do money calculations with integers (cents) or BCMath, and compare floats with a tolerance.
<?php
$cents = 1999 * 3;
echo number_format($cents / 100, 2) . " " . ($cents === 5997 ? "exact" : "not exact");
59.97 exact
Bug 7: “headers already sent”
<?php
echo "Welcome!";
header("Location: /dashboard");
exit;
Show the answer
header() must be called before any output. echo already sent the body. Remove the output (or buffer it with ob_start()), and check for stray whitespace or a byte order mark before <?php in included files.
<?php
header("Location: /dashboard");
exit;
Bug 8: users see each other’s data
<?php
$id = $_GET["id"];
$order = $pdo->query("SELECT * FROM orders WHERE id = $id")->fetch();
Name two problems.
Show the answer
- SQL injection (the id is joined into the SQL).
- IDOR (no check that the order belongs to the logged-in user).
<?php
$id = filter_var($_GET["id"] ?? null, FILTER_VALIDATE_INT);
$stmt = $pdo->prepare("SELECT id, total FROM orders WHERE id = :id AND user_id = :user");
$stmt->execute(["id" => $id, "user" => $_SESSION["user_id"]]);
$order = $stmt->fetch();
Bug 9: the names are in the wrong order
<?php
$names = ["ben", "Cara", "ana", "Dev"];
sort($names);
echo implode(", ", $names);
The list should be alphabetical, ignoring case. What is printed?
Show the answer
It prints Cara, Dev, ana, ben. By default sort() compares strings byte by byte, so every capital letter comes before every small letter. Ask for a case-insensitive sort:
<?php
$names = ["ben", "Cara", "ana", "Dev"];
sort($names, SORT_STRING | SORT_FLAG_CASE);
echo implode(", ", $names);
ana, ben, Cara, Dev
For human-friendly sorting of numbers inside text (file2, file10), use natcasesort() or SORT_NATURAL.
Bug 10: the cart is empty after redirect
<?php
$cart = ["pen"];
header("Location: cart.php");
exit;
// cart.php: var_dump($cart);
Show the answer
Variables do not survive a redirect: each request starts fresh. Store the cart in the session (or the database).
<?php
session_start();
$_SESSION["cart"] = ["pen"];
header("Location: cart.php");
exit;