Joomla-Registry-Objekte "mergen". Objekt wird Array? (Parameter $recursive)
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
val3wurde erwartungsgemäß mit dem Wert von$registry_1überschrieben. OK.val1undval2wurden wie erwartet dem$registry_2hinzugefügt. OK.- Zeile 16: Der Wert von
arr1ist unverändert vom Typarray. OK. - Zeile 9: Der Wert von
obj1ist ebenso Typarray, sollte aber einstdClass Objectsein. 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] => .
)

