Kod prezentował się następująco:
$this -> map('names', new opfArrayContainer(
new opfConstraint(MAP_TYPE, TYPE_STRING),
new opfConstraint(MAP_LEN_GT, 2)
), OPF_OPTIONAL);
$this -> map('surnames', new opfArrayContainer(
new opfConstraint(MAP_TYPE, TYPE_STRING),
new opfConstraint(MAP_LEN_GT, 2)
), OPF_OPTIONAL);
$this -> map('pesels', new opfArrayContainer(
new sConstraint(MAP_PESEL)
), OPF_OPTIONAL);
Innymi słowy, do skryptu musiało przyjść np. pole "names" będące tablicą z 30-ma komórkami, w których były poszczególne imiona. Okazało się, że gdy w takiej strukturze zrobiło się gdzieś błąd powodujący, że nie chciało to przejść przez kontrolę poprawności, renderer formularzy wariował i w ogóle nie wiedział, który komponent ma oznaczyć jako błędny. Ostatecznie dodałem do kodu biblioteki na sztywno obsługę stałej IGNORE_OPF_ERRORS, tak aby po prostu siedział wtedy cicho i wyświetlał formularz bez żadnego oznaczania na czerwono itd.
Oczywiście takie rozwiązanie na dłuższą metę nie przejdzie i trzeba wymyślić jakieś usprawnienie. W dodatku dobrze, aby to usprawnienie elegancko komponowało się z resztą kodu i faktycznie było intuicyjne do pojęcia, bo nie sztuka dodać coś w 20 minut, a miesiąc później klnąć, że się nie chciało dokładniej pomyśleć. Najlepsze są rozwiązania proste i skuteczne, dlatego zacząłem się zastanawiać, czy można opisać formularz kilkoma definicjami i przekształceniami tak, aby na ich podstawie można było uzyskać dowolną konfigurację z gwarancją, że OPF ją obsłuży. Mój pomysł opiera się na tym, aby zejść nieco głębiej i zrównać w definicji formularz oraz pole formularza. Powodem jest kilka podobieństw:
- Oba mogą mieć pewną wartość (przy czym dla formularza definiujemy ją jako zbiór wartości wszystkich pod-elementów)
- Oba mają pewien stan oraz mogą go zmieniać w trakcie przetwarzania.
- Oba są przetwarzane.
Teraz wystarczy, że potraktujemy formularz jako kontrolkę, która może przechowywać inne pola. Jeżeli spróbujemy teraz wymodelować powyższy przykład, wyglądałoby to mniej więcej tak: tworzymy sobie formularz dla pojedynczej osoby: Imię, Nazwisko, PESEL i coś tam jeszcze. Następnie osadzamy go w większym formularzu i zapętlamy tak, aby mógł pojawić się do 30-tu razy. Możemy także łatwo uzyskać efekt umieszczenia w opfArrayContainer() pojedynczego pola tak, jak to było dotychczas - po prostu umieszczamy w takiej pętli nie cały formularz, ale pojedynczą kontrolkę.
Pozostaje jeszcze kwestia nauczenia komponentów korzystania z takiej struktury, ale nie sądzę, aby było przesadnie skomplikowane, zwłaszcza w świetle tego, co szykuje nowy Open Power Template.
Ameryki kolega nie odkrył. Wzorzec Composite, czyli dokładnie to o czym piszesz jest bardzo dobrze znany - polecam sięgnąć czasem do literatury, nie trudno natknąć się na bardzo spokrewnione z tematem przykłady.
Bo ja nie jestem od odkrywania Ameryki, tylko tworzenia porządnych bibliotek :). Bardzo fajnie, że ten wzorzec projektowy już istnieje i ma swoją nazwę - teraz przypomniałem sobie, że faktycznie kiedyś o nim czytałem. Będzie można dzięki temu prościej wszystko udokumentować.
PS. Czy masz czas przeszukiwać bibliotekę książek za każdym razem, gdy wymyślisz coś nowego, by sprawdzić, czy przypadkiem tego ktoś już wcześniej nie wymyślił i nie nazwał? Think about it :).