Rector для PHP: полное руководство с примерами

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

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

Начать курс

Rector для PHP: полное руководство с примерами

Rector — это мощный инструмент для автоматического рефакторинга PHP-кода. Он представляет собой библиотеку, которая анализирует ваш код с помощью абстрактного синтаксического дерева (AST) и применяет к нему заданные правила трансформации. Это позволяет автоматизировать рутинные задачи по обновлению кода, такие как переход на новые версии PHP, внедрение новых фич языка, исправление устаревших конструкций и улучшение качества кода в целом.

Зачем нужен Rector? В современной PHP-разработке проекты быстро растут, и поддерживать их в актуальном состоянии становится всё сложнее. Ручной рефакторинг тысяч строк кода — это трудоёмкий и подверженный ошибкам процесс. Rector решает эту проблему, позволяя выполнять сложные преобразования за секунды. Он особенно полезен при обновлении с PHP 7.x на 8.x, при переходе с устаревших фреймворков (например, Zend Framework 1 на Laminas), или при внедрении строгих типов и современных паттернов.

Rector работает по принципу "набор правил". Вы определяете, какие преобразования нужно выполнить (например, "заменить все вызовы array_* на str_* функции"), а Rector находит все подходящие места в коде и вносит изменения. Инструмент полностью настраиваемый: вы можете использовать готовые наборы правил от сообщества или создавать свои собственные. Rector интегрируется в CI/CD пайплайны, что позволяет автоматически проверять и исправлять код при каждом коммите.

Установка

Rector устанавливается через Composer — стандартный менеджер пакетов для PHP. Выполните следующую команду в корне вашего проекта:

composer require rector/rector --dev

Флаг --dev означает, что пакет будет установлен только для разработки, что является правильной практикой, так как Rector не нужен в production-окружении.

После установки проверьте, что всё работает:

vendor/bin/rector --version

Если вы используете глобальную установку (не рекомендуется для проектов), можно выполнить:

composer global require rector/rector

Для работы Rector требуется PHP 7.2 или выше. Рекомендуется использовать PHP 8.0+ для максимальной производительности и поддержки всех возможностей.

Быстрый старт: минимальный рабочий пример

Создадим простой PHP-файл, который нужно отрефакторить. Допустим, у нас есть устаревший код, использующий create_function(), который был удалён в PHP 8.0.

Шаг 1. Создайте файл example.php:

<?php

$oldFunction = create_function('$a, $b', 'return $a + $b;');
echo $oldFunction(1, 2); // Выведет 3

Шаг 2. Создайте конфигурационный файл rector.php в корне проекта:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php80\Rector\Function_\CreateFunctionToAnonymousFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    // Указываем, какие директории анализировать
    $rectorConfig->paths([
        __DIR__ . '/example.php',
    ]);

    // Регистрируем правило для замены create_function на анонимные функции
    $rectorConfig->rule(CreateFunctionToAnonymousFunctionRector::class);
};

Шаг 3. Запустите Rector:

vendor/bin/rector process --dry-run

Флаг --dry-run покажет, какие изменения будут сделаны, но не применит их. Чтобы реально изменить файлы, выполните:

vendor/bin/rector process

Результат: Файл example.php будет преобразован в:

<?php

$oldFunction = function ($a, $b) {
    return $a + $b;
};
echo $oldFunction(1, 2); // Выведет 3

Этот простой пример демонстрирует основную идею: вы определяете правило, а Rector автоматически находит и исправляет все подходящие места в вашем коде.

Основные методы/функции/классы

Rector предоставляет богатый API для настройки и расширения. Ниже приведены 8 ключевых компонентов, с которыми вы будете работать чаще всего.

1. RectorConfig::paths()

Сигнатура: public function paths(array $paths): void

Что делает: Определяет список файлов или директорий, которые Rector будет анализировать и рефакторить. Это обязательный метод для конфигурации.

Пример:

<?php

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/src',
        __DIR__ . '/tests',
        __DIR__ . '/app/Controllers',
    ]);
};

2. RectorConfig::rule()

Сигнатура: public function rule(string $rectorClass): void

Что делает: Регистрирует одно правило рефакторинга. Правило — это класс, реализующий определённое преобразование кода. Можно регистрировать как встроенные правила, так и свои собственные.

Пример:

<?php

use Rector\Config\RectorConfig;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->rule(NullToStrictStringFuncCallArgRector::class);
};

3. RectorConfig::sets()

Сигнатура: public function sets(array $sets): void

Что делает: Подключает готовые наборы правил (sets). Это самый удобный способ применить сразу множество правил для обновления до определённой версии PHP или для внедрения определённого стиля кода.

Пример:

<?php

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->sets([
        SetList::PHP_80,
        SetList::PHP_81,
        SetList::CODE_QUALITY,
    ]);
};

4. RectorConfig::importNames()

Сигнатура: public function importNames(bool $import = true, bool $importDocBlock = true): void

Что делает: Включает или отключает автоматический импорт имён классов (use statements). Полезно для приведения кода к современному стандарту, где все классы импортируются явно.

Пример:

<?php

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->importNames();
    // или с настройками:
    // $rectorConfig->importNames(true, false); // только для кода, не для docblock
};

5. RectorConfig::skip()

Сигнатура: public function skip(array $skips): void

Что делает: Позволяет исключить определённые файлы, директории или даже конкретные правила из обработки. Это необходимо, когда некоторые части кода не должны изменяться (например, сторонние библиотеки или legacy-код).

Пример:

<?php

use Rector\Config\RectorConfig;
use Rector\Php80\Rector\Function_\CreateFunctionToAnonymousFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->skip([
        // Пропустить всю директорию vendor
        __DIR__ . '/vendor',
        // Пропустить конкретный файл
        __DIR__ . '/src/Legacy/OldFile.php',
        // Пропустить конкретное правило для конкретного файла
        CreateFunctionToAnonymousFunctionRector::class => [
            __DIR__ . '/src/ThirdParty/SomeLibrary.php',
        ],
    ]);
};

6. RectorConfig::autoloadPaths()

Сигнатура: public function autoloadPaths(array $autoloadPaths): void

Что делает: Указывает дополнительные пути для автозагрузки классов. Это полезно, если ваш проект использует нестандартную структуру автозагрузки, и Rector не может найти классы.

Пример:

<?php

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->autoloadPaths([
        __DIR__ . '/vendor/autoload.php',
        __DIR__ . '/src/autoload.php',
    ]);
};

7. RectorConfig::phpVersionFeatures()

Сигнатура: public function phpVersionFeatures(string $phpVersion): void

Что делает: Устанавливает целевую версию PHP, для которой Rector будет генерировать код. Это важно, когда вы пишете код для одной версии, но хотите, чтобы он был совместим с более старой или новой.

Пример:

<?php

use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;

return static function (RectorConfig $rectorConfig): void {
    // Целевая версия PHP 8.1
    $rectorConfig->phpVersionFeatures(PhpVersion::PHP_81);
};

8. RectorConfig::withPhpSets()

Сигнатура: public function withPhpSets(bool $php80 = false, bool $php81 = false, bool $php82 = false, bool $php83 = false): void

Что делает: Удобный метод для включения сразу всех правил, связанных с конкретной версией PHP. Это современная альтернатива использованию sets() для версионных обновлений.

Пример:

<?php

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    // Включить все правила для PHP 8.1 и 8.2
    $rectorConfig->withPhpSets(
        php81: true,
        php82: true,
    );
};

Реальный практический пример

Рассмотрим реальный сценарий: у нас есть проект на PHP 7.4, который мы хотим обновить до PHP 8.1. В проекте используется старый код с array_* функциями, которые в PHP 8.1 имеют более строгие сигнатуры, а также устаревшие конструкторы и отсутствие типов.

Создадим файл src/UserService.php:

<?php

namespace App\Service;

class UserService
{
    private $users;

    public function __construct()
    {
        $this->users = [];
    }

    public function addUser($name, $email)
    {
        $this->users[] = ['name' => $name, 'email' => $email];
    }

    public function getUsers()
    {
        return $this->users;
    }

    public function findUser($email)
    {
        $filtered = array_filter($this->users, function($user) use ($email) {
            return $user['email'] === $email;
        });
        return array_values($filtered)[0] ?? null;
    }

    public function updateUser($email, $newName)
    {
        foreach ($this->users as &$user) {
            if ($user['email'] === $email) {
                $user['name'] = $newName;
                return true;
            }
        }
        return false;
    }
}

Теперь создадим конфигурационный файл rector.php:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/src',
    ]);

    // Подключаем наборы правил для PHP 8.1 и качества кода
    $rectorConfig->sets([
        SetList::PHP_81,
        SetList::CODE_QUALITY,
        SetList::TYPE_DECLARATION,
    ]);

    // Дополнительные правила
    $rectorConfig->rule(AddVoidReturnTypeWhereNoReturnRector::class);
    $rectorConfig->rule(TypedPropertyFromStrictConstructorRector::class);

    // Включаем импорт имён
    $rectorConfig->importNames();

    // Исключаем тестовые файлы
    $rectorConfig->skip([
        __DIR__ . '/tests',
    ]);
};

Запустим Rector:

vendor/bin/rector process --dry-run

После применения изменений (без флага --dry-run) файл UserService.php будет преобразован в:

<?php

namespace App\Service;

class UserService
{
    private array $users;

    public function __construct()
    {
        $this                    

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