Automatische Migration mit Rector
Rector ist ein PHP-Refactoring-Tool, das automatisch Code transformieren kann. REDAXO 6 verwendet Rector, um die Migration von Add-ons von REDAXO 5.x auf 6.x zu automatisieren.
Installation
1. Rector als Dev-Dependency hinzufügen
composer require --dev rector/rector
2. Rector-Konfiguration erstellen
Erstelle eine rector.php Datei im Wurzelverzeichnis deines Add-ons:
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\Name\RenameClassRector;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\Rector\StaticCall\RenameStaticMethodRector;
use Rector\Renaming\ValueObject\MethodCallRename;
use Rector\Renaming\ValueObject\RenameStaticMethod;
use Rector\Transform\Rector\FuncCall\FuncCallToStaticCallRector;
use Rector\Transform\ValueObject\FuncCallToStaticCall;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/lib',
__DIR__ . '/pages',
__DIR__ . '/boot.php',
__DIR__ . '/install.php',
__DIR__ . '/uninstall.php',
__DIR__ . '/update.php',
])
->withImportNames()
// Klassen umbenennen
->withConfiguredRule(RenameClassRector::class, [
// Core-Klassen
'rex' => 'Redaxo\\Core\\Core',
'rex_addon' => 'Redaxo\\Core\\Addon\\Addon',
'rex_sql' => 'Redaxo\\Core\\Database\\Sql',
'rex_sql_table' => 'Redaxo\\Core\\Database\\Table',
'rex_sql_column' => 'Redaxo\\Core\\Database\\Column',
'rex_article' => 'Redaxo\\Core\\Content\\Article',
'rex_category' => 'Redaxo\\Core\\Content\\Category',
'rex_clang' => 'Redaxo\\Core\\Language\\Language',
'rex_user' => 'Redaxo\\Core\\Security\\User',
'rex_form' => 'Redaxo\\Core\\Form\\Form',
'rex_config_form' => 'Redaxo\\Core\\Form\\ConfigForm',
'rex_list' => 'Redaxo\\Core\\View\\DataList',
'rex_fragment' => 'Redaxo\\Core\\View\\Fragment',
'rex_view' => 'Redaxo\\Core\\View\\View',
'rex_path' => 'Redaxo\\Core\\Filesystem\\Path',
'rex_url' => 'Redaxo\\Core\\Filesystem\\Url',
'rex_file' => 'Redaxo\\Core\\Filesystem\\File',
'rex_dir' => 'Redaxo\\Core\\Filesystem\\Dir',
'rex_request' => 'Redaxo\\Core\\Http\\Request',
'rex_response' => 'Redaxo\\Core\\Http\\Response',
'rex_csrf_token' => 'Redaxo\\Core\\Security\\CsrfToken',
'rex_logger' => 'Redaxo\\Core\\Log\\Logger',
'rex_i18n' => 'Redaxo\\Core\\Translation\\I18n',
'rex_extension' => 'Redaxo\\Core\\ExtensionPoint\\Extension',
'rex_extension_point' => 'Redaxo\\Core\\ExtensionPoint\\ExtensionPoint',
'rex_media' => 'Redaxo\\Core\\MediaPool\\Media',
'rex_media_category' => 'Redaxo\\Core\\MediaPool\\MediaCategory',
'rex_exception' => 'Redaxo\\Core\\Exception\\Exception',
'rex_validator' => 'Redaxo\\Core\\Validator\\Validator',
'rex_string' => 'Redaxo\\Core\\Util\\Str',
'rex_formatter' => 'Redaxo\\Core\\Util\\Formatter',
'rex_mailer' => 'Redaxo\\Core\\Mailer\\Mailer',
// Weitere Klassen nach Bedarf hinzufügen
// Vollständige Liste: siehe migration-klassen.md
])
// Globale Funktionen zu statischen Methoden
->withConfiguredRule(FuncCallToStaticCallRector::class, [
new FuncCallToStaticCall('rex_get', 'Redaxo\\Core\\Http\\Request', 'get'),
new FuncCallToStaticCall('rex_post', 'Redaxo\\Core\\Http\\Request', 'post'),
new FuncCallToStaticCall('rex_request', 'Redaxo\\Core\\Http\\Request', 'request'),
new FuncCallToStaticCall('rex_cookie', 'Redaxo\\Core\\Http\\Request', 'cookie'),
new FuncCallToStaticCall('rex_session', 'Redaxo\\Core\\Http\\Request', 'session'),
new FuncCallToStaticCall('rex_set_session', 'Redaxo\\Core\\Http\\Request', 'setSession'),
new FuncCallToStaticCall('rex_unset_session', 'Redaxo\\Core\\Http\\Request', 'unsetSession'),
new FuncCallToStaticCall('rex_server', 'Redaxo\\Core\\Http\\Request', 'server'),
new FuncCallToStaticCall('rex_getUrl', 'Redaxo\\Core\\Filesystem\\Url', 'article'),
new FuncCallToStaticCall('rex_delete_cache', 'Redaxo\\Core\\Cache', 'delete'),
])
// Methoden umbenennen
->withConfiguredRule(RenameMethodRector::class, [
new MethodCallRename('Redaxo\\Core\\Content\\Article', 'getClang', 'getClangId'),
new MethodCallRename('Redaxo\\Core\\Content\\Category', 'getClang', 'getClangId'),
new MethodCallRename('Redaxo\\Core\\Content\\ArticleSlice', 'getClang', 'getClangId'),
new MethodCallRename('Redaxo\\Core\\Addon\\Addon', 'getRegisteredPackages', 'getRegisteredAddons'),
new MethodCallRename('Redaxo\\Core\\Addon\\Addon', 'getAvailablePackages', 'getAvailableAddons'),
])
// Statische Methoden verschieben
->withConfiguredRule(RenameStaticMethodRector::class, [
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'addCssFile', 'Redaxo\\Core\\View\\Asset', 'addCssFile'),
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'addJsFile', 'Redaxo\\Core\\View\\Asset', 'addJsFile'),
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'error', 'Redaxo\\Core\\View\\Message', 'error'),
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'success', 'Redaxo\\Core\\View\\Message', 'success'),
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'info', 'Redaxo\\Core\\View\\Message', 'info'),
new RenameStaticMethod('Redaxo\\Core\\View\\View', 'warning', 'Redaxo\\Core\\View\\Message', 'warning'),
])
;
Rector ausführen
Vorschau (Dry-Run)
Zuerst die Änderungen prüfen, ohne Dateien zu modifizieren:
vendor/bin/rector process --dry-run
Änderungen anwenden
vendor/bin/rector process
Vollständige REDAXO 6 Rector-Konfiguration
Die offizielle und vollständige Rector-Konfiguration findest du im REDAXO 6.x Branch:
Repository: github.com/redaxo/redaxo
Branch: 6.x
Datei: rector.php
Diese enthält alle Transformationsregeln für:
- Über 200 Klassenumbenennungen
- Methodenumbenennungen
- Funktionen zu statischen Methoden
- Parameter-Änderungen
- Konstanten-Migration
Verwendung der offiziellen Konfiguration
Du kannst die offizielle Konfiguration als Basis verwenden:
# REDAXO 6 Repository klonen
git clone --branch 6.x https://github.com/redaxo/redaxo.git redaxo6
# Rector-Konfiguration kopieren
cp redaxo6/rector.php ./rector.php
# Pfade in rector.php anpassen
Passe dann die ->withPaths([...]) Konfiguration an die Struktur deines Add-ons an.
Beispiel: Add-on Migration
Vorher (REDAXO 5.x)
<?php
class my_addon_helper
{
public static function getData($articleId)
{
$clang = rex_clang::getCurrentId();
$article = rex_article::get($articleId, $clang);
if (!$article) {
throw new rex_exception('Article not found');
}
$sql = rex_sql::factory();
$sql->setTable(rex::getTable('mydata'));
$sql->setWhere(['article_id' => $articleId]);
$sql->select();
return $sql->getArray();
}
}
// Im Template/Modul
$id = rex_get('id', 'int', 0);
echo rex_view::success('Daten geladen');
rex_view::addCssFile(rex_addon::get('my_addon')->getAssetsUrl('style.css'));
Nachher (REDAXO 6.x)
<?php
use Redaxo\Core\Addon\Addon;
use Redaxo\Core\Content\Article;
use Redaxo\Core\Core;
use Redaxo\Core\Database\Sql;
use Redaxo\Core\Exception\Exception;
use Redaxo\Core\Http\Request;
use Redaxo\Core\Language\Language;
use Redaxo\Core\View\Asset;
use Redaxo\Core\View\Message;
class my_addon_helper
{
public static function getData($articleId)
{
$clang = Language::getCurrentId();
$article = Article::get($articleId, $clang);
if (!$article) {
throw new Exception('Article not found');
}
$sql = Sql::factory();
$sql->setTable(Core::getTable('mydata'));
$sql->setWhere(['article_id' => $articleId]);
$sql->select();
return $sql->getArray();
}
}
// Im Template/Modul
$id = Request::get('id', 'int', 0);
echo Message::success('Daten geladen');
Asset::addCssFile(Addon::get('my_addon')->getAssetsUrl('style.css'));
Schrittweise Migration
Für größere Add-ons empfiehlt sich eine schrittweise Migration:
Schritt 1: Nur Klassen umbenennen
return RectorConfig::configure()
->withPaths([__DIR__ . '/lib'])
->withConfiguredRule(RenameClassRector::class, [
// Nur Kernklassen
'rex' => 'Redaxo\\Core\\Core',
'rex_sql' => 'Redaxo\\Core\\Database\\Sql',
// ...
])
;
Schritt 2: Funktionen migrieren
->withConfiguredRule(FuncCallToStaticCallRector::class, [
new FuncCallToStaticCall('rex_get', 'Redaxo\\Core\\Http\\Request', 'get'),
// ...
])
Schritt 3: Methoden anpassen
->withConfiguredRule(RenameMethodRector::class, [
new MethodCallRename('Redaxo\\Core\\Content\\Article', 'getClang', 'getClangId'),
// ...
])
Tipps für die Migration
1. Backup erstellen
git checkout -b redaxo6-migration
2. Tests ausführen (falls vorhanden)
# Vor Migration
vendor/bin/phpunit
# Nach Migration
vendor/bin/phpunit
3. Manuelle Nacharbeit
Rector kann nicht alle Änderungen automatisch durchführen:
- package.yml:
requiresaufredaxo: ^6.0anpassen -
Eigene Namespaces: PSR-4 Autoloading für eigene Klassen einrichten
Lege deine eigenen Klassen z. B. im Verzeichnis
src/ab und richte in dercomposer.jsondeines Add-ons einen passenden PSR-4-Namespace ein:```json { “autoload”: { “psr-4”: { “Vendor\\MeinAddon\\”: “src/” } } }
- Entfernte Features: Code für entfernte Funktionen manuell anpassen
4. IDE-Unterstützung
Nach der Migration die IDE-Indizes aktualisieren:
- PhpStorm:
File → Invalidate Caches / Restart - VS Code: PHP Intelephense neu starten
Häufige Probleme
Problem: Klasse nicht gefunden
Class 'rex' not found
Lösung: Use-Statement hinzufügen:
use Redaxo\Core\Core;
Problem: Methode existiert nicht
Call to undefined method getClang()
Lösung: Methode wurde umbenannt. Siehe migration-methoden.md
Problem: Funktion existiert nicht
Call to undefined function rex_get()
Lösung: Globale Funktion durch statische Methode ersetzen:
use Redaxo\Core\Http\Request;
$value = Request::get('key', 'string');
Weiterführende Dokumentation
- Klassen Migration - Vollständige Tabelle aller Klassenzuordnungen
- Methoden Migration - Alle Methodenänderungen
- Funktionen Migration - Globale Funktionen → statische Methoden
- Rector Dokumentation - Offizielle Rector-Dokumentation