Bardzo lubię kolekcję Laravel'a, ale ostatnio mi zmarnowały kilka godzin. Przyjmijmy pseukod:
$aspects = Collection::class;
return $users->transform(function($user) use ($aspects) {
$aspects = deep_clone($aspects, [Collection::class, Aspect::class]);
$aspects->transform(function($aspect) use ($user) {
$aspect->transform(function(Aspect $level) use ($user) {
// sth
});
return $aspect;
});
$user->aspects = $aspects;
return $user;
});
Mamy kolekcję z użytkownikami, z kilkoma poziomami zagnieżdżeń (relacjami). Chciałby zmodyfikować troszkę strukturę kolekcji edytując, czy dodając pewne elementy dynamiczne do obiektów w środku. Spoko, zadanie dla transform
. I zmarnowałem kilka godzin, ponieważ cały czas nie umiałem efektu osiągnąć, myśląc, że to może problem z transform
zamiast map
, itp. A problem jest zupełnie innej natury, i to nie typowo Frameworkowej. Kolekcje to są obiekty obiektów, a te przekazywane są za pomocą referencji. Starą szkołą, gdzie większość struktur była tablicami, takie edytowanie struktury drzewkowej było bardzo intuicyjne, w przypadku kodu powyżej za każdym razem dostawałem użytkowników, z tym dodatkowym atrybutem ustawionym tak samo dla wszystkich (jak dla ostatniego usera). No ok, nasuwa się troszkę zaciemniające kod - copy. Skopiujemy aspects przy każdym obrocie pętli i będzie ok. Niestety pudło, copy kopiuję kolekcję, a nie same obiekty więc efekt ciągle taki sam. Dopiero potrzebne by było napisanie takiego brzydkiego copy + copy na każdym elemencie i wtedy to zadziała, i tak dla każdego parametru zewnętrznego, który ulega modyfikacjom i każdego zagnieżdżenia.
Nie mogłem na to patrzeć więc napisałem własnego helpera deep_clone, który używa hackowego unserialize(serialize(())
+ jako parametr lista klas, inaczej IDE mi krzyczy, że to dziura :)
Nie da się ładniej? Kolekcje są ok, dopóki nie chcemy w nich troszkę namieszać?