Introduction: Why Is Your Code Being Rewritten?
\n\nYou wrote the code. It works. You're proud of yourself. But then code review comes, and the senior developer leaves 15 comments, half of which start with "What if..." or "Let's rewrite this as...". Sound familiar?
\n\nPHP code review is not about nitpicking. It's about project survival. Seniors don't just look at "works/doesn't work," but at how the code will behave under load, how another developer will maintain it, and how much time you'll spend hunting for a bug six months from now.
\n\nIn this article, we'll break down the most common comments you'll hear during a code review from an experienced PHP developer. I'll show real code examples and explain how to fix them. After reading, you'll be able to anticipate 80% of the comments and write code you won't be ashamed to show.
\n\n1. "Magic Numbers" and Strings: Code Should Speak for Itself
\n\nThe first thing a senior will notice is unclear numbers and strings scattered throughout the code. Magic numbers are an antipattern that kills readability.
\n\nBad Example
\nif ($user->getAge() > 18) {\n $discount = $price * 0.1;\n}\n\nWhat Will the Senior Say?
\n- \n
- Why exactly 18? Is this the age of majority or a discount threshold? \n
- Why 0.1? Is that 10%? What if the discount changes? \n
Good Example
\nconst ADULT_AGE = 18;\nconst DISCOUNT_RATE = 0.1; // 10%\n\nif ($user->getAge() > ADULT_AGE) {\n $discount = $price * DISCOUNT_RATE;\n}\n\nNow the code tells a story. The senior will approve: constants can be reused, changed in one place, and they don't require comments.
\n\n2. Lack of Types: PHP 8 Is No Excuse for Dynamic Typing
\n\nPHP is a weakly typed language, but that doesn't mean you should write code like it's 2005. Strict typing saves you from bugs that are hard to catch.
\n\nBad Example
\nfunction calculateTotal($items, $tax) {\n $total = 0;\n foreach ($items as $item) {\n $total += $item['price'] * $item['quantity'];\n }\n return $total * (1 + $tax);\n}\n\nSenior's Comments
\n- \n
- What is
$items? An array? An object? A collection? \n - What is the structure of an element? Why no DTO? \n
- What if
$taxis passed as the string "0.2"? Will it concatenate? \n
Good Example
\ndeclare(strict_types=1);\n\nclass OrderItem {\n public function __construct(\n public readonly float $price,\n public readonly int $quantity\n ) {}\n}\n\nfunction calculateTotal(array $items, float $taxRate): float {\n $total = 0.0;\n foreach ($items as $item) {\n if (!$item instanceof OrderItem) {\n throw new InvalidArgumentException('Expected OrderItem');\n }\n $total += $item->price * $item->quantity;\n }\n return $total * (1 + $taxRate);\n}\n\nThe senior will say: "Good job, you're using DTO, readonly properties, and strict typing. The code is predictable." This is a PHP 8+ best practice.
3. Deep Nesting and Early Return
\n\nWhen you see 5 levels of if...else inside a single method, the senior grabs their head. Such code is impossible to read, test, and debug.
Bad Example
\npublic function processOrder($order) {\n if ($order->isPaid()) {\n if ($order->hasStock()) {\n if ($order->isShippable()) {\n // 50 lines of logic\n return $this->ship($order);\n } else {\n throw new \\Exception('Order cannot be shipped');\n }\n } else {\n throw new \\Exception('Out of stock');\n }\n } else {\n throw new \\Exception('Order not paid');\n }\