10 PHP Bugs That Break Real Projects — And How to Fix Them (Part 2)
Every PHP developer has lived this nightmare. The code runs perfectly on localhost. You deploy to production. Something silently breaks —…
10 PHP Bugs That Break Real Projects — And How to Fix Them (Part 2)

Every PHP developer has lived this nightmare. The code runs perfectly on localhost. You deploy to production. Something silently breaks — no error, no log, just wrong output and a few wasted hours tracing the problem. These bugs do not come from textbooks. They come from actual PHP projects: login systems, e-commerce stores, admin panels, school management portals, and APIs.
This is Part 2 of the PHP Real-Time Bugs series. We cover Bug #11 through Bug #20, each with the broken code, the correct fix, and a clear explanation of what actually goes wrong in production.
🎥 Watch the video walkthrough here: https://youtube.com/shorts/BpE1WmEfoUs?si=HTNpTou8FLepcuyn
Bug #11 — Infinite Loop from a Missing Counter Increment
A forgotten $i++ inside a while loop locks up the PHP process entirely. On a shared server, this can take down the application for all users until the request times out. If the loop also touches a database, you are now firing thousands of repeated queries. One missing line — enormous consequences.
Bug #12 — String Comparison Failing Because of Letter Case
PHP string comparisons are case-sensitive by default. If your role-based access control checks $_POST['role'] == "Admin", any user who types "admin" or "ADMIN" either gets denied or incorrectly granted access. Always normalize with strtolower() before comparing, and store values in lowercase in the database too.
Bug #13 — Integer Cast Cutting Off Decimals in Division
PHP returns 2.5 for 5 / 2 — that is correct. But casting it with (int) truncates to 2, not rounds. In billing systems, GST calculations, or cart totals, this kind of truncation produces real financial errors on every invoice. Use round() for rounding and number_format() for display output. Never cast floats to integers unless you explicitly intend to drop the decimal.
Bug #14 — JSON Decode Returning an Object Instead of an Array
By default, json_decode() returns a PHP stdClass object. Accessing it with bracket notation like $data['name'] throws a fatal error. Passing true as the second argument forces an associative array — which is more consistent when working with API responses throughout your codebase. Also add json_last_error() checks, because API responses can and do arrive malformed.
Bug #15 — Printing User Input Directly to HTML (XSS Vulnerability)
Echoing $_GET['name'] without escaping it means an attacker can inject a <script> tag into your page. That script executes in the browser of every visitor who loads that URL. The fix is always htmlspecialchars() with ENT_QUOTES and 'UTF-8' as the charset — every single time you print user input to HTML. No exceptions.
Bug #16 — Relative Include Paths Breaking on Different Servers
Relative paths in PHP resolve based on the current working directory, not the file’s own directory. On localhost with XAMPP or WAMP this might work. On a live Apache or Nginx server with different virtual host settings, the same path fails completely. Using __DIR__ — a PHP magic constant that always returns the absolute path of the current file's directory — eliminates the ambiguity across all environments.
Bug #17 — Duplicate Database Entries from Form Resubmission
Two real-world causes: users double-clicking the submit button on slow connections, and browsers resubmitting POST data when the page is refreshed. The fix requires two layers — a PHP-side existence check before inserting, plus a UNIQUE constraint at the database level so simultaneous requests cannot both slip through. After a successful submission, always redirect with header("Location: ...") to prevent resubmission on refresh.
Bug #18 — array_merge Resetting Numeric Keys
array_merge() reindexes all numeric keys starting from zero. If you are merging configuration arrays, working with database results keyed by IDs, or building data structures where key values matter, array_merge() silently destroys your key structure without any warning. Use the + union operator to preserve keys (left side wins on conflict), or array_replace() if you want the right array's values to win.
Bug #19 — No Error Logging Set Up in Production
Turning off display_errors in production is correct — you do not want stack traces visible to users or attackers. But many developers stop there and configure no logging either. Errors then disappear completely. You have no record of what broke or when. The correct setup: disable display, enable log_errors, and set an error_log path. For professional-grade monitoring, tools like Sentry or Bugsnag give real-time error alerts with full stack traces.
Bug #20 — foreach Not Modifying the Original Array
foreach works on a copy of each element by default. Any changes inside the loop have no effect on the original array — which looks like it should work, and does not. Adding & before the variable makes it a reference to the actual array element. Critically, you must call unset($price) after the loop ends — otherwise $price still references the last element and any later use of that variable name will silently corrupt your array. Alternatively, array_map() is a clean, reference-free option.
What These Bugs Have in Common
Most of them do not throw errors. PHP’s forgiving nature means the code runs — it just does not do the right thing. That is exactly what makes them dangerous in production. No warning. No crash. Just silent wrong behavior that costs hours to trace.
The developers who catch these early are the ones who have seen them before, or who studied them before getting burned. That is the value of real-world bug analysis over textbook syntax exercises.
Read the full article with complete code examples here: 👉 10 PHP Bugs That Break Real Projects — And How to Fix Them (Part 2)
Part 3 of this series covers bugs #21–30 — session handling, file upload security, date and timezone bugs, and database connection errors.
Found this useful? Follow for more real-world PHP debugging content.
메타데이터
- post_id
- 5943ce4e0fe1
- slug
- 10-php-bugs-that-break-real-projects-and-how-to-fix-them-part-2-5943ce4e0fe1
- url
- https://medium.com/@bikkisingh/10-php-bugs-that-break-real-projects-and-how-to-fix-them-part-2-5943ce4e0fe1
- canonical_url
- https://medium.com/@bikkisingh/10-php-bugs-that-break-real-projects-and-how-to-fix-them-part-2-5943ce4e0fe1
- author_url
- https://medium.com/@bikkisingh
- status
- ok
- fetched_at
- 2026-06-18 07:02:39