You write what looks like perfectly reasonable PHP.
You hit refresh.
Blank. White. Screen.
No error. No warning. Nothing.
If you've been there — welcome to the club. Every PHP beginner goes through this. The frustrating part isn't that PHP is hard. It's that PHP fails silently by default, which makes debugging feel impossible until you know the tricks.
I put together the 10 bugs I see beginners hit over and over again. Fix these once, and you'll stop seeing the same crashes on repeat.
🔧 Before Anything Else: Turn Error Reporting ON
Seriously. Do this first. Everything else on this list is twice as hard without it.
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Put this at the very top of your file during development. PHP hides errors by default — this forces it to speak up.
⚠️ Never run this in production. Log to a file there instead.
Bug #1 — The Blank White Screen (Syntax Error)
The classic beginner jumpscare. You add one line, hit refresh, and get nothing.
<?php
$username = "Sanvi" // 👈 Missing semicolon — PHP chokes here silently
echo "Hello, " . $username;
Fix it:
<?php
$username = "Sanvi"; // Semicolons end every statement
echo "Hello, " . $username;
With error_reporting(E_ALL) on, PHP tells you exactly which line broke. Without it — good luck.
Bug #2 — Loose Comparison Traps (== vs ===)
This one genuinely surprises people. PHP's == does type coercion before comparing:
var_dump("0" == false); // bool(true) 😬
var_dump(0 == "foo"); // bool(true) in PHP 7 — bool(false) in PHP 8
Fix it: Use === by default. Always.
if ($userInput === false) {
// Only runs if it's actually a boolean false
}
=== checks both value AND type — no coercion, no surprises.
Bug #3 — Undefined Variable Warnings
Notice: Undefined variable: userName
Your page might still load, but your logic is already broken.
echo "Welcome, " . $userName; // Was it ever assigned? Typo? Wrong scope?
Fix it:
$userName = $_GET['name'] ?? 'Guest'; // Null coalescing — clean PHP 7+ syntax
echo "Welcome, " . $userName;
The ?? operator returns the right side when the left is null or missing. Much cleaner than isset() chains.
Bug #4 — Variable Scope Inside Functions
PHP doesn't automatically share global variables into functions. This trips everyone up at least once.
$siteName = "MyApp";
function showHeader() {
echo $siteName; // Notice: Undefined variable 😅
}
Fix it:
function showHeader(string $name): void {
echo "<h1>" . htmlspecialchars($name) . "</h1>";
}
showHeader($siteName); // Pass it in as a parameter
Passing values as parameters > using the global keyword. It's cleaner, testable, and doesn't create hidden dependencies.
Bug #5 — SQL Injection from Raw Queries 🚨
This isn't just a bug. It's a vulnerability. And I've seen it in production codebases that were years old.
// NEVER do this:
$userId = $_GET['id'];
$query = "SELECT * FROM users WHERE id = " . $userId;
// Attacker sends: ?id=1 OR 1=1 — now they get every row
Fix it — always use prepared statements:
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
The ? placeholder locks the query structure before user input is inserted. The database treats it as data, not SQL.
Bug #6 — Skipping htmlspecialchars() on Output
SQL injection attacks your database. XSS (Cross-Site Scripting) attacks your users.
// If $comment is <script>alert('hacked')</script> — that runs in the browser 😬
echo "<p>" . $_POST['comment'] . "</p>";
Fix it:
$safe = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8');
echo "<p>" . $safe . "</p>";
ENT_QUOTES handles single AND double quotes. UTF-8 prevents encoding tricks. Both matter.
Bug #7 — "Headers Already Sent" Error
Warning: Cannot modify header information — headers already sent by...
You tried to call header() after PHP already sent output. Even one space before <?php causes this.
<?php
echo "Loading..."; // Output sent here
header("Location: /dashboard.php"); // 💥 Too late
Fix it:
<?php
// Zero output before header() calls
if (!$isLoggedIn) {
header("Location: /login.php");
exit(); // 👈 Always exit after redirecting
}
echo "Welcome!";
exit() after header() is not optional. Without it, the rest of your script keeps running even while the browser redirects.
Bug #8 — Array Key Errors Without Checks
$email = $_POST['email']; // If 'email' wasn't submitted — Undefined index 💥
Fix it:
$email = trim($_POST['email'] ?? '');
if ($email !== '') {
// Safe to process
}
?? handles missing keys. trim() removes accidental whitespace. Both matter for form input.
Bug #9 — include vs require Confusion
They look the same. They're not.
include |
require |
|
|---|---|---|
| File missing | Warning → script continues | Fatal error → script stops |
| Best for | Optional templates | Critical files (DB, config) |
include 'db_connection.php';
// File missing? PHP keeps running... straight into a crash on the next DB call
Fix it:
require_once 'db_connection.php';
// File missing? PHP stops immediately with a clear, useful error
Use require_once for anything your script cannot live without.
Bug #10 — Ignoring Return Values
PHP functions return false on failure. If you don't check, you'll call methods on false and get confusing errors:
$fileContents = file_get_contents('/path/to/missing-file.txt');
$lines = explode("\n", $fileContents); // Warning: expects string, bool given 😬
Fix it:
$fileContents = file_get_contents('/path/to/config.txt');
if ($fileContents === false) {
throw new RuntimeException("Config file could not be read.");
}
$lines = explode("\n", $fileContents); // Safe now ✅
One unchecked return value can cascade into ten confusing errors downstream. Always check.
TL;DR — 4 Habits That Fix 80% of PHP Bugs
✅ Turn on error_reporting(E_ALL) in development
✅ Use === instead of == by default
✅ Always check return values before using them
✅ Sanitize everything that touches a user or a database
None of these require advanced knowledge. Just consistent discipline.
What's Next?
Take any existing PHP project and audit it against this list. You'll probably find at least 3-4 of these hiding somewhere.
👉 Full article with deeper explanations: Top 10 PHP Bugs Every Beginner Makes (And How to Fix Them)
Got a PHP bug that's haunted you? Drop it in the comments — let's debug it together 👇