Ein Code-Schnipsel zwischendrin. Registry-Objekte sind eine feine Joomla-Sache und können viele eigene Zeilen Code einsparen. Wie bei "normalen" PHP-Objekten kan man key-value-Paare reintun und mehrere Registry-Objekte ähnlich dem bekannten array_merge in ein einzelnes zusammenfassen. Ist einer der values allerdings ein stdClass Object, wird daraus beim unachtsamen mergen unerwünscht ein array.

Beispiel-Szenario-Code eines "Joomla-Registries-Merge"

// Erstellen des 1. Registry-Objektes:
$registry_1 = new JRegistry;

// Erstellen des 2. Registry-Objektes:
$registry_2 = new JRegistry;

// Erstellen und befüllen eines stinknormalen PHP-Test-Objekts:
$obj1 = new stdClass;
$obj1->a = 'a';
$obj1->b = 'b';
$obj1->c = 'c';

// Zum Vergleich des Verhaltens noch ein stinknormales Test-Array:
$arr1 = ['d', 'e', 'f'];

// Ein paar Testdaten in registry_1:
$registry_1->set('val1', 1);
$registry_1->set('val2', 2);
$registry_1->set('val3', 2456);

// Ein paar Testdaten in registry_2:
$registry_2->set('val3', 3);
$registry_2->set('val4', 4);

// Und, wichtig, stinknormale PHP-Objekt und PHP-Array in registry_1  als Werte packen:
$registry_1->set('obj1', $obj1);
$registry_1->set('arr1', $arr1);

// Jetzt die beiden zusammen-mergen, also registry_1 über registry_2 "bügeln":
$registry_2->merge($registry_1);

// Verändertes registry_2-Ergebnis anzeigen:
echo '<pre>' . print_r($registry_2, true) . '</pre>';exit;

"Falsches" $registry_2-Ergebnis

Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [val3] => 2456
            [val4] => 4
            [val1] => 1
            [val2] => 2
            [obj1] => Array
                (
                    [a] => a
                    [b] => b
                    [c] => c
                )

            [arr1] => Array
                (
                    [0] => d
                    [1] => e
                    [2] => f
                )

        )

    [initialized:protected] => 1
    [separator] => .
)

Anna Lühse des "falschen", resultierenden $registry_2

  • val3 wurde erwartungsgemäß mit dem Wert von $registry_1 überschrieben. OK.
  • val1 und val2 wurden wie erwartet dem $registry_2 hinzugefügt. OK.
  • Zeile 16: Der Wert von arr1 ist unverändert vom Typ array. OK.
  • Zeile 9: Der Wert von obj1 ist ebenso Typ array, sollte aber ein stdClass Object sein. Das ist nicht OK, außer man will das so. Kann ja manchmal auch prickelnd praktisch sein.

Löh Sung des Problems

Füge dem merge() ein true hinzu, damit das object ein stdClass Object bleibt. Siehe dazu Parameter $recursive der merge-Methode der Klasse Registry https://github.com/joomla/joomla-cms/blob/3.9.28/libraries/vendor/joomla/registry/src/Registry.php#L397

// Jetzt die beiden zusammen-mergen, also registry_1 über registry_2 "bügeln".
// Aber diesmal mit $recursive = true:
$registry_2->merge($registry_1, true);

"Richtiges" Ergebnis (Auszug)

[obj1] => stdClass Object
    (
	   [a] => a
	   [b] => b
	   [c] => c
    )

Der Vollständigkeit halber: Objekt-Instanzen gehen beim merge() verloren

Ob es einen Trick gibt, weiß ich nicht.

Im folgenden Code erstelle ich eine Instanz der Yaml-Klasse (oder sonsteiner), füge sie einem Registry-Objekt als Variable hinzu, danach merge ich das Ganze in ein zweites Registry-Objekt.

Während vor dem Mergen mir diese Instanz korrekt im ersten Debug-Code (print_r) angegeben wird (Symfony\Component\Yaml\Yaml Object), ist sie im zweiten nurmehr ein stdClass Object.

// Yaml-Klassen-Instanz: Symfony\Component\Yaml\Yaml Object
$yaml = new Symfony\Component\Yaml\Yaml;
$yaml->ding = 'Dung';

$registry_1 = new JRegistry;
$registry_2 = new JRegistry;

$registry_1->set('yaml', $yaml);

echo '$registry_1: <pre>' . print_r($registry_1, true) . '</pre>';

$registry_2->merge($registry_1, true);
echo '$registry_2 nach dem Merge: <pre>' . print_r($registry_2, true) . '</pre>';exit;

Ausgabe

$registry_1:

Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [yaml] => Symfony\Component\Yaml\Yaml Object
                (
                    [ding] => Dung
                )

        )

    [initialized:protected] => 
    [separator] => .
)

$registry_2 nach dem Merge:

Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [yaml] => stdClass Object
                (
                    [ding] => Dung
                )

        )

    [initialized:protected] => 1
    [separator] => .
)