Как пройти собеседование по PHP: продвинутые вопросы и ответы

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как пройти собеседование по 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+ по

Блоги

Рекомендаций по книгам