Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: dynamiczne rozszerzanie klasy, pluginy - wzorzec?
Forum PHP.pl > Forum > PHP > Object-oriented programming
baniczek
Witam

Potrzebowałbym nowego podejścia do rzeczy, którą chcę wykonać.
W celu opisania problemu muszę się trochę rozpisać... ;-)

"miniframework" -> generowanie formularzy
klasę Form reprezentującą formularz rozszerzam klasą Form_PHP. w niej w metodzie create() wywoluję metody:

Kod
$this->add_input_text('nazwa', array('class' => 'php'))->add_textarea('nazwa2')->add_input_submit('Zapisz'); itp.


w klasie Form używam metody __call() w celu pobrania nazwy klasy elementu formularza - czyli "add_" jest odrzucane, Input_Text to klasa.

Jest możliwe tworzenie grup (checkbox, radio) metodą:
Kod
$this->add_group('checkboxy[]', array('wartosc_1' => 'label_1', itd), array('class' => 'grupa'));


Problem narodził się z wymogu dodania np. klasy do jednego elementu grupy radio/checkbox - tablice wielowymiarowe to dość średnie rozwiązanie i chciałem wszystko w jednym "łańcuchu" zrobić. Nie chciałem również w klasie formularza tworzyć ręcznie obiektów grupy i dlatego powstało coś takiego:
Kod
$this
    ->group_start('checkboxy[]', array('class' => 'asd'))
        ->add('wartosc_1', 'label_1', array('class' => 'klasa czekboksa'))
        ->add('wartosc_2', 'label_2', array('id' => 'cosinnego'))
        ...
    ->group_end()


To wszystko generalnie działa, lecz problem narodził w czasie kiedy chciałem tą funkcjonalność zamknąć w osobnej klasie.

Utworzyłem proste api do pseudo pluginów, które dynamicznie rozszerzają klasę Form o nowe metody. I tak np. w magicznej metodzie __call() klasy Form odbywa się sprawdzanie (zaraz na początku), czy któryś plugin ma metodę np. group_start(). Z tym nie ma problemów - jak nie ma metody to leci dalej, jak ma - wywołuje.


Jednak w celu ogarnięcia tego chociażby z powodu, że za kilka dni zapomnę co napisałem, chciałem zrobić sprawdzanie czy metoda wywołana na klasie Form istnieje w aktualnie używanym pluginie - w przypadku kiedy metody są zamknięte między innymi. To też działa, ale nie w przypadku, który obecnie rozpatruje:

Zaprezentowana wyżej metoda group_end() wywołuje nic innego, jak metodę (na klasie Form) ->add_group() z odpowiednimi parametrami - czyli jest obsługiwana przez __call() w klasie Form. Z racji, że sprawdzanie czy metoda pluginu istnieje w nim odbywa się zaraz na początku __call() w klasie Form to sprawdzany jest ostatnio używany plugin (czyli ten od grupy, group_start()) i zamiast dodać grupę jest wyrzucany wyjątek, że metoda add_group() nie istnieje w pluginie - co nie jest dziwne.
Mogę przenieść sprawdzanie na koniec __call(), ale wtedy raczej nie możliwe będzie utworzenie lub nadpisanie metody istniejącej w klasie Form, np. w przypadku kiedy zamykam metody między 2 metodami pluginu. Czyli metoda pluginu: add() zamknięta pomiędzy 2 innymi metodami, a metoda add() istnieje w klasie Form i ma całkiem inne zastosowanie niż ta pluginowa - dlatego wywołujemy tą z pluginu jeśli "praca na pluginie" nie została zakończona.

Po co "ostatnio używany plugin"? Np. powyższy przypadek i też po to, że tych pluginów może być wiele i wszystkie mogą zawierać metodę ->add() i żeby w dobrym pluginie ją wywołać to trzeba (?) przechować obecny plugin.
"Pracę na pluginie" w praktyce oznacza wartość zwracana z metody pluginu, np. self::RESULT_PLUGIN - pracujemy na pluginie czyli następna metoda jest brana z tego pluginu (np. ta jedna konkretna metoda add() z wielu metod o takiej samej nazwie w pluginach czy też w klasie Form), self::RESULT_FORM - koniec operacji na pluginie (np. group_end() ją zwraca) czyli zmienna z ostatnim pluginem jest czyszczona, następna metoda to metoda z innego pluginu lub z klasy Form.

Mam jeden pomysł, który rozwiązywałby ten problem, ale nie chcę go stosować smile.gif Tworzę zmienną $_wylacz_pluginy np. w klasie Form, ustawiam na TRUE w metodzie group_end() (w pluginie), wywołuję metodę add_group() na klasie Form w tejże metodzie pluginu (w tym momencie pluginy wyłączone i leci dalsza część __call() czyli metoda add_group() jest wywoływana ), ustawiam zmienną $_wylacz_pluginy na FALSE i wszystko działa. Jest to rozwiązanie złe moim zdaniem, zbyt dużo trzeba pamiętać a i kod nie wygląda dobrze.

Czy jest inny sposób?
Czy to co próbuję zrobić podchodzi może pod wzorzec projektowy (którego nie potrafię znaleźć wink.gif?
Czy to da się zrobić?
Czy ktoś próbował coś podobnego wykonać?

Pozdrawiam
marcio
Nie bardzo zrozumialem podaj wiecej kodu, ogolnie rzecz biorac zrob ujednolicone API i nie bedziesz mial problemow z wywolywaniem metod z plugin-ow.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.