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 value
s 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
undval2
wurden wie erwartet dem$registry_2
hinzugefügt. OK.- Zeile 16: Der Wert von
arr1
ist unverändert vom Typarray
. OK. - Zeile 9: Der Wert von
obj1
ist ebenso Typarray
, sollte aber einstdClass 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] => .
)