Почему code review — это не про "найти баги"
Представьте: вы написали идеальный код. Он работает, проходит тесты, даже клиент доволен. Но на code review приходит коллега и... начинается. "А почему здесь ==, а не ===?", "Этот метод делает 5 дел сразу", "Где обработка исключений?". Знакомо?
На самом деле, code review на PHP — это не охота на баги (хотя и это тоже). Это способ сделать код читаемым, безопасным и поддерживаемым. Особенно в PHP, где за 25 лет эволюции накопилось много "грабель".
В этой статье мы разберём, что проверять на code review PHP, чтобы код не просто работал, а был эталоном качества. Готовы? Поехали!
1. Типизация и строгие режимы
PHP 7+ и 8 дали нам мощные инструменты для контроля типов. Но многие проекты до сих пор живут в "режиме хаоса".
Что проверять:
- Объявлены ли типы аргументов и возвращаемых значений? Если метод принимает
int, а передаётеstring— это повод для разговора. - Есть ли
declare(strict_types=1);в начале файла? Без этого PHP будет неявно приводить типы, что часто приводит к скрытым ошибкам.
<?php
declare(strict_types=1);
// Плохо: нет типов
function calculate($a, $b) {
return $a + $b;
}
// Хорошо: строгая типизация
function calculate(int $a, int $b): int {
return $a + $b;
}
?>
Совет для code review: если видите mixed или array без спецификации — задайте вопрос "А что именно здесь ожидается?".
2. Безопасность: SQL-инъекции и XSS
PHP — как швейцарский нож: много функций, и многие из них опасны. Особенно в legacy-коде.
Топ-3 красных флага:
- Конкатенация в SQL-запросах. Если видите
"SELECT * FROM users WHERE id = ".$_GET['id']— это вопль о помощи. - Вывод данных без экранирования.
echo $userInput;— привет XSS. - Хранение паролей в plain text. Серьёзно, это всё ещё встречается.
<?php
// Опасно!
$sql = "SELECT * FROM users WHERE email = '" . $email . "'";
// Безопасно (PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $email]);
?>
На code review PHP всегда проверяйте работу с внешними данными. Любой $_GET, $_POST, $_COOKIE должен проходить через фильтрацию.
3. Следование PSR-стандартам
PHP-сообщество придумало PSR (PHP Standards Recommendations) не для галочки. Это — язык, на котором говорят все PHP-разработчики.
Что должно быть в каждом PR:
- PSR-12 (стиль кодирования): отступы 4 пробела, фигурные скобки на новой строке для классов, пробелы вокруг операторов.
- PSR-4 (автозагрузка): неймспейсы должны совпадать с путём к файлу.
- Имена классов —
StudlyCaps, методы —camelCase, константы —UPPER_CASE.
<?php
namespace App\Service;
class UserService // PSR-4: файл должен лежать в src/Service/UserService.php
{
public function getUserById(int $id): ?User // camelCase
{
// ...
}
}
?>
Лайфхак: если в проекте нет автоматического форматирования (PHP CS Fixer, PHP_CodeSniffer) — это первый пункт для улучшения.
4. Сложность и архитектура
Хороший код — это код, который можно прочитать как книгу. А плохой — как расшифровку древнего манускрипта.
На что обращать внимание:
- Длина метода. Если метод больше 20-30 строк — скорее всего, он делает слишком много.
- Уровень вложенности. Три уровня
ifвнутриforeach— сигнал к рефакторингу. - Магические числа и строки.
if ($status == 3)— что такое 3? Выносите в константы.
<?php
// Плохо: магическое число и много вложенности
function processOrder($order) {
if ($order->status == 3) {
if ($order->total > 1000) {
// ...
}
}
}
// Хорошо: константа + early return
const STATUS_COMPLETED = 3;
function processOrder(Order $order): void {
if ($order->status !== STATUS_COMPLETED) {
return;
}
// ...
}
?>
На код ревью PHP задавайте вопрос: "Можно ли этот метод разбить на два?" или "Что делает эта функция, если смотреть на название?"
5. Обработка ошибок и исключений
PHP — терпимый язык. Он простит вам многое: необъявленную переменную, отсутствие обработки ошибки... пока не придёт время деплоя в пятницу вечером.
Красные флаги в PR:
- Голый
try {} catch (Exception $e) {}— проглатывание ошибки. - Использование
@для подавления ошибок (оператор контроля ошибок). - Отсутствие
finallyдля закрытия ресурсов (файлы, соединения с БД).
<?php
// Плохо: подавление ошибки
$content = @file_get_contents('config.json');
// Хорошо: явная обработка
try {
$content = file_get_contents('config.json');
if ($content === false) {
throw new RuntimeException('Не удалось прочитать файл конфигурации');
}
} catch (RuntimeException $e) {
// Логируем и показываем пользователю понятное сообщение
error_log($e->getMessage());
throw $e; // или возвращаем fallback-значение
}
?>
Важно: проверяйте, что разработчик не использует Exception как универсальный класс. В современном PHP лучше создавать свои классы исключений.
6. Работа с базой данных и ORM
Если проект использует Doctrine, Eloquent или просто PDO — есть нюансы.