Как пройти собеседование по PHP: топ вопросов продвинутого уровня
Собеседование на позицию Senior PHP-разработчика — это не просто проверка синтаксиса. Работодатель оценивает архитектурное мышление, понимание внутреннего устройства языка, опыт работы с высоконагруженными системами и знание современных стандартов. В этой статье мы разберём ключевые вопросы продвинутого уровня с практическими примерами, которые помогут вам уверенно пройти техническое интервью.
1. SOLID в PHP: принципы и примеры нарушений
Вопрос о SOLID — классика любого собеседования. Важно не просто перечислить принципы, но и показать, как их нарушение приводит к проблемам, и как их исправить.
Принцип единственной ответственности (SRP). Класс должен иметь только одну причину для изменения. Рассмотрим типичное нарушение:
class User {
public function save() { /* сохранение в БД */ }
public function sendEmail() { /* отправка письма */ }
public function generateReport() { /* генерация отчёта */ }
}
Здесь класс User отвечает и за сохранение, и за уведомления, и за отчёты. Правильный подход — вынести каждую ответственность в отдельный сервис:
class UserRepository {
public function save(User $user) { /* ... */ }
}
class MailService {
public function sendWelcomeEmail(User $user) { /* ... */ }
}
class ReportGenerator {
public function generate(User $user) { /* ... */ }
}
Принцип открытости/закрытости (OCP). Классы должны быть открыты для расширения, но закрыты для модификации. Вместо if-else используйте полиморфизм:
// Нарушение OCP
class PaymentProcessor {
public function pay(string $type) {
if ($type === 'credit_card') { /* ... */ }
elseif ($type === 'paypal') { /* ... */ }
}
}
// Правильное решение
interface PaymentMethod {
public function process();
}
class CreditCardPayment implements PaymentMethod {
public function process() { /* ... */ }
}
class PayPalPayment implements PaymentMethod {
public function process() { /* ... */ }
}
class PaymentProcessor {
public function pay(PaymentMethod $method) {
$method->process();
}
}
На собеседовании обязательно упомяните, что для PHP важен также принцип инверсии зависимостей (DIP) — зависимость от абстракций, а не от конкретных классов. Покажите пример с Dependency Injection:
class OrderService {
private PaymentMethod $paymentMethod;
public function __construct(PaymentMethod $paymentMethod) {
$this->paymentMethod = $paymentMethod;
}
public function checkout() {
$this->paymentMethod->process();
}
}
2. Паттерны проектирования: когда и зачем
Вопросы про паттерны на собеседовании проверяют, умеете ли вы применять типовые решения в реальных задачах. Недостаточно просто назвать паттерн — нужно объяснить, какую проблему он решает.
Singleton (Одиночка). Используется для объектов, которые должны существовать в единственном экземпляре (например, подключение к БД). Но будьте готовы к критике: многие считают Singleton анти-паттерном из-за скрытых зависимостей и проблем с тестированием.
class Database {
private static ?Database $instance = null;
private function __construct() { }
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
Factory Method (Фабричный метод). Создаёт объекты без указания конкретного класса. Особенно полезен при работе с разными типами подключений:
interface Connection { }
class MysqlConnection implements Connection { }
class PostgresConnection implements Connection { }
class ConnectionFactory {
public static function create(string $type): Connection {
return match($type) {
'mysql' => new MysqlConnection(),
'postgres' => new PostgresConnection(),
default => throw new \InvalidArgumentException("Unknown type"),
};
}
}
Strategy (Стратегия). Позволяет менять алгоритм на лету. Отлично подходит для реализации различных способов сортировки или валидации:
interface SortStrategy {
public function sort(array $data): array;
}
class QuickSort implements SortStrategy {
public function sort(array $data): array { /* быстрая сортировка */ }
}
class MergeSort implements SortStrategy {
public function sort(array $data): array { /* сортировка слиянием */ }
}
class Sorter {
private SortStrategy $strategy;
public function __construct(SortStrategy $strategy) {
$this->strategy = $strategy;
}
public function sort(array $data): array {
return $this->strategy->sort($data);
}
}
3. PSR стандарты и современный PHP
Знание PSR (PHP Standard Recommendations) — обязательное требование для Senior-разработчика. Основные стандарты, которые нужно знать:
- PSR-1 — базовые правила кодирования (теги, кодировка, побочные эффекты).
- PSR-4 — автозагрузка классов через Composer (упрощённая версия PSR-0).
- PSR-7 — интерфейсы HTTP-сообщений (Request, Response).
- PSR-11 — интерфейс контейнера зависимостей (Container Interface).
- PSR-12 — расширенный стиль кодирования (замена PSR-2).
Пример PSR-4 структуры проекта:
src/
App/
Controller/
UserController.php // namespace App\Controller;
Service/
UserService.php // namespace App\Service;
config/
routes.php
public/
index.php
composer.json
Composer-секция для PSR-4:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Также стоит упомянуть атрибуты PHP 8 — как более современную альтернативу аннотациям PHPDoc:
#[Route('/api/users', methods: ['GET'])]
class UserController {
#[Inject]
private UserService $userService;
#[Route('/{id}', requirements: ['id' => '\d+'])]
public function show(int $id): Response { /* ... */ }
}
4. Кэширование и производительность
Вопросы про кэширование — проверка опыта работы с высоконагруженными проектами. Основные подходы:
Opcode кэширование. PHP 8+ по