REDAXO AddOns und Namespaces

Quell-ID: GitHub Discussion #40

Use Case

REDAXO-AddOns sollen für die zukünftige Composer-Integration vorbereitet werden. Dafür ist die Umstellung auf Namespaces nach PSR-4 Standard erforderlich.

Verwendete AddOns

  • REDAXO Core
  • Alle FOR-AddOns (zur Umstellung)

Hintergrund

Die REDAXO-Community arbeitet an einer standardisierten Composer-Integration. Dafür ist die Verwendung von Namespaces in AddOns wichtig.

Namespace-Konventionen

Schema

«Publisher»\«AddonName»

Für FriendsOfREDAXO-AddOns

FriendsOfRedaxo\AddonName

Beispiele

Repository Namespace
FriendsOfREDAXO/focuspoint FriendsOfRedaxo\Focuspoint
FriendsOfREDAXO/geolocation FriendsOfRedaxo\Geolocation
FriendsOfREDAXO/yform_adminer FriendsOfRedaxo\YFormAdminer
TobiasKrais/d2u_helper TobiasKrais\D2UHelper

Namensregeln

  1. Publisher: Erstellername, z.B. FriendsOfRedaxo, MeinName, MeinPseudonym
  2. AddonName: CamelCase ohne Unterstriche, z.B. YFormAdminer statt yform_adminer
  3. Abkürzungen: Nicht zu viele Großbuchstaben, z.B. HtmlHelper statt HTMLHelper
  4. Redaxo\: Nur für Pakete im Haupt-REDAXO-Repo

Umstellung einer Datei

Vorher (ohne Namespace)

<?php
rex_perm::register('yform_adminer[]');

if (rex::isBackend()) {
    $user = rex::getUser();
    if (null !== $user && $user->hasPerm('yform_adminer[]')) {
        YFormAdminer::init();
    }
}

Nachher (mit Namespace)

<?php
namespace FriendsOfRedaxo\YFormAdminer;

use rex;
use rex_addon;
use rex_perm;

rex_perm::register('yform_adminer[]');

if (rex::isBackend()) {
    $user = rex::getUser();
    if (null !== $user && $user->hasPerm('yform_adminer[]')) {
        YFormAdminer::init();
    }
}

Welche Dateien können Namespaces haben?

  • ✅ Dateien im lib-Verzeichnis
  • boot.php
  • install.php / update.php / uninstall.php
  • ✅ Fragmente
  • ✅ YForm-Fragmente

Einschränkungen

Einige Klassen können derzeit keine Namespaces haben, da sie über ihr Namensschema aufgefunden werden:

  • rex_api_xxx
  • rex_effect_xxx
  • rex_yform_value_xxx
  • rex_yform_action_xxx
  • rex_yform_validate_xxx
  • rex_var_xxx

API-Klassen können mit Namespace registriert werden:

class MyApiClass extends \rex_api_function { ... }

// In boot.php registrieren
\rex_api_function::register('myapi', MyApiClass::class);

Besserer Ansatz: Callbacks modernisieren

Bei der Umstellung Callbacks modernisieren:

Alt

rex_extension::register('EP_NAME', 'klasse::methode');
rex_extension::register('EP_NAME', array('klasse', 'methode'));

Neu

rex_extension::register('EP_NAME', Klasse::methode(...));

Klassennamen

// Alt
is_a($media, 'FocuspointMedia');

// Neu
is_a($media, FocuspointMedia::class);

Migration mit Rückwärtskompatibilität

<?php
// lib/Xyz.php (neuer Namespace)
namespace FriendsOfRedaxo\MyAddon;

class Xyz 
{
    public static function doSomething(): void
    {
        // ...
    }
}
<?php
// lib/no_namespace/xyz.php (Kompatibilität)

/**
 * @deprecated 4.0.0 Aufrufe auf "FriendsOfRedaxo\MyAddon\Xyz" umstellen
 */
class xyz_alt extends FriendsOfRedaxo\MyAddon\Xyz
{
}

Autoloading mit PSR-4

// composer.json im AddOn
{
    "autoload": {
        "psr-4": {
            "FriendsOfRedaxo\\MyAddon\\": "lib/"
        }
    }
}

Die Verzeichnisstruktur muss zum Namespace passen:

lib/
├── Xyz.php              → FriendsOfRedaxo\MyAddon\Xyz
├── Helper/
│   └── StringHelper.php → FriendsOfRedaxo\MyAddon\Helper\StringHelper
└── YForm/
    └── Dataset/
        └── Product.php  → FriendsOfRedaxo\MyAddon\YForm\Dataset\Product

Empfehlung

Namespaces sind noch nicht Pflicht, aber dringend empfohlen. Entwickler sollten neue AddOns direkt mit Namespace erstellen und bestehende AddOns schrittweise umstellen.