Top 10 PHP Bugs Every Beginner Makes (And How to Fix Them)

php dev.to

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);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Fix it:

<?php
$username = "Sanvi"; // Semicolons end every statement
echo "Hello, " . $username;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Fix it: Use === by default. Always.

if ($userInput === false) {
    // Only runs if it's actually a boolean false
}
Enter fullscreen mode Exit fullscreen mode

=== 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?
Enter fullscreen mode Exit fullscreen mode

Fix it:

$userName = $_GET['name'] ?? 'Guest'; // Null coalescing — clean PHP 7+ syntax
echo "Welcome, " . $userName;
Enter fullscreen mode Exit fullscreen mode

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 😅
}
Enter fullscreen mode Exit fullscreen mode

Fix it:

function showHeader(string $name): void {
    echo "<h1>" . htmlspecialchars($name) . "</h1>";
}

showHeader($siteName); // Pass it in as a parameter
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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>";
Enter fullscreen mode Exit fullscreen mode

Fix it:

$safe = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8');
echo "<p>" . $safe . "</p>";
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Fix it:

<?php
// Zero output before header() calls

if (!$isLoggedIn) {
    header("Location: /login.php");
    exit(); // 👈 Always exit after redirecting
}

echo "Welcome!";
Enter fullscreen mode Exit fullscreen mode

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 💥
Enter fullscreen mode Exit fullscreen mode

Fix it:

$email = trim($_POST['email'] ?? '');

if ($email !== '') {
    // Safe to process
}
Enter fullscreen mode Exit fullscreen mode

?? 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
Enter fullscreen mode Exit fullscreen mode

Fix it:

require_once 'db_connection.php';
// File missing? PHP stops immediately with a clear, useful error
Enter fullscreen mode Exit fullscreen mode

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 😬
Enter fullscreen mode Exit fullscreen mode

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 ✅
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 👇

Source: dev.to

arrow_back Back to Tutorials