Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Zasady pisania na forum Pro

Tematy na forum Pro mogą zakładać jedynie moderatorzy. W otwartych tematach może pisać każdy, kto ma coś fachowego do powiedzenia. Wszystkie posty nie wnoszące nic do tematu będą natychmiast usuwane, a ich autorzy dostaną ostrzeżenie.
Jeśli uważasz, że jakiś temat jest warty dyskusji na tym forum, zgłoś go w temacie Propozycje.

5 Stron V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Aplikacje PHP - Pluginy
Zeman
post 4.04.2007, 13:12:58
Post #41





Grupa: Zarejestrowani
Postów: 70
Pomógł: 0
Dołączył: 29.03.2007

Ostrzeżenie: (0%)
-----


To ja też wtrące swoje 0,03 PLN.

Na początek napiszę że moje rozumowanie pluginów wzięło się z pisania w Delphi aplikacji będących serwerami COM. Także moje poniższe rozważania trochę są ukierunkowane w stronę COM aniżeli w stronę PHP winksmiley.jpg takie zboczenie zawodowe.

Przede wszystkim należy sobie zdać sprawę że są różne rodzaje pluginów - pluginy ogólnego przeznaczenia i pluginy dedykowane jakiejś funkcjonalności. Te pierwsze jest dużo trudniej wprowadzić w życie.
Projektując system pluginów najpierw sobie musimy zadać pytanie do czego mają być te pluginy. Powiedzmy, że zbudowaliśmy jakiś system i chcemy dać możliwość rozbudowy go poprzez pluginy. Po pierwsze, najlepiej zabronić grzebania w kodzie głównym, gdyż to będzie powodowało destabilizacje pozostałych pluginów. Możemy kod główny, np klasy opatrzeć np w interfejsy i nakazać, żeby plugin korzystał tylko z tychże interfejsów. Warto uzewnętrznić zdarzenia np. w klasie TUser zdarzenia onLogin(...) onLogout(...) onRegister itd. W projekcie niech będzie powiedzmy singleton manager pluginów i taki taki singleton ma mieć dostęp do wszelkich instancji klas kodu głównego, czyli np Manager ma mieć dostęp do obiektu $user klasy TUser. Ponadto, każda instancja pluginu ma się zgłaszać do managera że się powołuje do życia.
Należy też wymyśleć i zdefiniować czym jest plugin, przykładowo plugin to jest obiekt takiej klasy, która implementuje interfejs IPlugin. Interfejs ten niech ma metody pozwalające sterować się managerowi. Manager przyjmował będzie zgłoszenia tworzenia nowych pluginów i będzie je dodawał do swojej listy, jednocześnie będzie miał możliwość coś zrobienia z każdym takim pluginem dzięki interfejsowi IPlugin.

Przykład:
Memy manager będący singletonem TPManager,
mamy obiekt użytkownika typu TUser.
Obiekt użytkownika udostępnia zdarzenie onLogin(..).
Manager ma pole $user, czyli np. TPManager::instance()->user;
Niech interfejs IPlugin ma metodę doOnRegister(..)

Tworzony jest obiekt - plugin, mający na celu jakąś reakcję na zalogowanie się, powiedzmy sprawdza czy user ma nowe wiadomości i je wyrzuca na ekran. Taki tworzony plugin zgłasza się do managera, manager go rejestruje na swojej liście. Dodatkowo, manager po dodaniu pluginu na listę wywołuje jego metodę doOnRegister(...), a ta metoda, odwołuje się poprzez manager do obiektu usera i rejestruje w nim swoje zdarzenie onLogin.
Teraz powiedzmy, że użytkownik się loguje, zatem wywoływana zostaje metoda powiedzmy TPManager::instance()->user->tryLogin(..). W tej metodzie jest kod logujący i w przypadku udanego logowania wywołuje $this->onLogin(). $this->onLogin wywołuje wszystkie zarejestrowane u siebie zdarzenia, czyli wywołuje zdarzenie z podłączonego pluginu, a to już sprawdza czy są nowe wiadomości i w razie czego wali je na ekran.

Ale natłukłem tekstu, ciekawe czy komuś będzie sie chciało tyle czytac winksmiley.jpg

Pozwiodronka,
Zeman.

Dodam że sam nie korzystam z tego co opisałem winksmiley.jpg Pluginowość załatwia mi plugin dyrektyw w moim edytorze PHP, tylko sobie klikam checkboxy które pluginy a właściwie moduły chce mieć w danym projekcie i ten mi wypluwa kod PHP okrojony z pozostałych pluginów, coś w rodzaju (na podstawie poprzedniego przykładu):
  1. <?php
  2. class TUser {
  3. function tryLogin() {
  4.  ... // logowanie
  5.  {$IFDEF "modul_sprawdzania_wiadomosci"}
  6. ... // kod do sprawdzania wiadomości
  7.  {$ENDIF}
  8. }
  9. }
  10. ?>


Pozwiodronka,
Zeman.


--------------------
www.web2biz.pl | trochę o web-usability
Go to the top of the page
+Quote Post
Athlan
post 6.04.2007, 08:34:47
Post #42





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

Ostrzeżenie: (0%)
-----


Cytat
Ale natłukłem tekstu, ciekawe czy komuś będzie sie chciało tyle czytac


Przeczytałem bardzo dokładnie i pozwolę sobie dokonać analizy.

W Twoim przypadku wykonujesz jakieś pluginy przed wykonaniem metody lub/i po niej. Np Login() => onLogin() (podobnie do JavaScriptu). Pomysł bardzo dobry, wręcz genialny, ale sprawdzanie, czy metoda istnieje za kazdym razem spowolni zleksza aplkiacje hm?

Ok do rzeczy. Tak jak przedstawiłem w moim poprzednim poście, przyczepmy się tego naszego BBCode. Trzeba jakoś treść newsa przepóścić przez metodę BBCode::Parse() a jest to niezbędne albo w kontrolerze, albo w templacie. Nie chcemy tutaj ingerować w kod aplikacji. Dzięki rozwiązaniu Zeman'a możemy zrobić tak, że obiekt widoku jest trzymany jako argument kontrolera, przez co jest w stanie używalności przez cały czas. Do czego zmierzam. Kolejność wykonywania poszczególnych metod:

$oController->preLogin(metoda_pluginu_jakiegos); // wykonamy PRZED kontrolerem Login
$oController->outLogin(metoda_pluginu_jakiegos); // wykonamy tuż przed executem widoku w kontrolerze przez dispatcher, ale po wykonaniu wszelkich akcji wewnątrz kontrolera
$oView = $oController->Login(); // każdy kontroler zwraca obiekt widoku;
$oView->display(); // no i execute

W czym rzecz... metoda outLogin() wykonana zostanie po wszelkich działaniach kontrolera, ale jeszcze przed wyrzuceniem (return) widoku, co pozwoli nam na dowolną ingerencję w kontroler zaraz po wykonaniu operacji. W naszym przypadku (BBCode) filtrujemy sobie jeden argument z idoku przechowywanym jako argument kontrolera:

  1. <?php
  2. outLogin()
  3. {
  4. $this->LoadPlugin('BBcode');
  5.  
  6. $this->oView->news_content = BBCode::Parse($this->oView->news_content); // bbcode
  7. $this->oView->news_content_long = BBCode::Smileys($this->oView->news_content); // emotikony w dlugiej czesci newsa
  8. }
  9. ?>


To by było na tyle z mojej strony, ciekawe czy ktoś przeczyta smile.gif

Cytat
Pozwiodronka,
Zeman.


Zdraviam smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
Zeman
post 6.04.2007, 10:53:11
Post #43





Grupa: Zarejestrowani
Postów: 70
Pomógł: 0
Dołączył: 29.03.2007

Ostrzeżenie: (0%)
-----


Cytat(Athlan @ 6.04.2007, 09:34:47 ) *
To by było na tyle z mojej strony, ciekawe czy ktoś przeczyta smile.gif


Przeczytałem, ale wiele z tego nie rozumiem, może dlatego, że nie znam BBCode. W moim rozumowaniu pluginów bardziej to podchodzi pod "pluginy dedykowane" o których wspomniałem w podziale pluginów ale ich nie opisywałem. A może się pokuszę o napisanie mikro-artykułu winksmiley.jpg Tylko czy ktoś to będzie czytał...


--------------------
www.web2biz.pl | trochę o web-usability
Go to the top of the page
+Quote Post
faster
post 15.04.2007, 22:44:14
Post #44





Grupa: Zarejestrowani
Postów: 49
Pomógł: 0
Dołączył: 9.09.2002
Skąd: Pszczyna

Ostrzeżenie: (0%)
-----


Cytat
Tylko czy ktoś to będzie czytał...


Witam,
... czytam, czytam ... dokładnie i sam się zastanawiam jak podejść do tematu.
Zgadzam się na pewno z jednym, pluginy to rozszerzenia funkcji systemu zatem trzeba najpierw zaplanować co chcemy aby było rozszerzane. Słyszałem o systemach które są ponoć całkowicie rozszerzalne i można pisać pluginy do wszystkiego ale czy to przypadkiem nie polega na przepisywaniu czy modyfikacji istniejącego już w systemie kodu? Bo nie potrafię sobie wyobrazić jak można rozszerzyć wszystko smile.gif w aplikacji.
Zastanawia mnie natomiast jeszcze inna rzecz .... jak trzeba zaprojektować genialnie aplikację aby była tak rozszerzalna jak firefox smile.gif co Wy na to?

Pozdrawiam
::faster
Go to the top of the page
+Quote Post
Zeman
post 15.04.2007, 23:18:06
Post #45





Grupa: Zarejestrowani
Postów: 70
Pomógł: 0
Dołączył: 29.03.2007

Ostrzeżenie: (0%)
-----


Cytat(faster @ 15.04.2007, 23:44:14 ) *
Witam,
... czytam, czytam ... dokładnie i sam się zastanawiam jak podejść do tematu.
Zgadzam się na pewno z jednym, pluginy to rozszerzenia funkcji systemu zatem trzeba najpierw zaplanować co chcemy aby było rozszerzane. Słyszałem o systemach które są ponoć całkowicie rozszerzalne i można pisać pluginy do wszystkiego ale czy to przypadkiem nie polega na przepisywaniu czy modyfikacji istniejącego już w systemie kodu? Bo nie potrafię sobie wyobrazić jak można rozszerzyć wszystko smile.gif w aplikacji.
Zastanawia mnie natomiast jeszcze inna rzecz .... jak trzeba zaprojektować genialnie aplikację aby była tak rozszerzalna jak firefox smile.gif co Wy na to?

Pozdrawiam
::faster



Aplikacje typu FF sa serwerami COM'opodobnymi, które udostępniają na zewnątrz kupę interfejsów. Pisząc plugin pisze się tak naprawdę aplikację kliencką która wykorzystuje te uzewnętrznione interfejsy żeby coś na nich robić. Jak można się domyślać FF ma swoje wewnętrzne obiekty, te obiekty implementują interfejsy. Interfejsy są "przedefiniowane" na tzn język IDL, który stanowi jakby pomost pomiędzy różnymi językami - IDL stanowi standard opisywania interfejsów. Aplikacje - pluginy z grubsza powiedziawszy odczytują definicje interfejsów z tego IDLa i przedefiniowują je na język w którym jest pisany plugin. Najczęściej języki wspierają tworzenie tzw wrapperów. Z punktu widzenia autora pluginu wrapper to obiekt będący klonem obiektu w aplikacji serwera, czyli np jeśli FF ma obiekt powiedzmy Document, to w pluginie też istnieje obiekt Document o tych samych metodach, jednak w pluginie obiekt ten jest wrapperem na obiekt w FF - czyli jeśli plugin wywoła Document->metoda(), to tak naprawdę wywoła się metoda() ale w FF. FF z tego co mi wiadomo wykorzystuje XPCOM i jest to technologia podobna do COM i CORBA, tyle że cross-platform. COM nie jest cross-platform.
Suma sumarum wlaśnie tak się robi aplikacje typu FF - odrazu się zakłada że aplikacja będzie serwerem COM i wszystkim nowo tworzonym klasom nadaje się cechę bycia obiektem COM, co jest równoznaczne z tym, że klasa będzie udostępniała na zewnątrz interfejsy do języka IDL. Dalej się nie będę rozwodził na ten temat ale jest to dosyć trudne zagadnienie no i to forum jest o PHP a wątek dotyczy pluginów w PHP a nie pluginów w FF winksmiley.jpg


--------------------
www.web2biz.pl | trochę o web-usability
Go to the top of the page
+Quote Post
yaotzin
post 3.05.2007, 20:44:09
Post #46





Grupa: Zarejestrowani
Postów: 157
Pomógł: 0
Dołączył: 12.02.2007
Skąd: Zielona Góra

Ostrzeżenie: (0%)
-----


Witam nie przeczytałem wszystkich postów bo nie mam czasu teraz i moze sie powtórzę smile.gif Ale chciałbym zauważyć wiele stron internetowych jest postawionych na czymś takim jak joomla! W joomla aby rozszerzyć możliwości tego framework'a wystarczy doinstalować nowe moduły lub komponenty, jako że pierwsze rozszerzają tylko funkcjonalność serwisu i nie wnoszą nowych modyfikacji, to te drugie w oparciu o API Joomla w dużym stopniu zmieniają działanie seriwsu i to co widzi użytkownik na stronie. Działanie tego elementu w joomla jest niemalże niezawodne, i sprawuje się doskonale, zapewne ma jakieś ograniczenia, ale wydaje mi się że implementowanie czegoś takiego jak moduły w joomla! jest w sumie dosyć proste i chcę taką rzecz za jakiś czas robić (oczywiście przy wolnej chwili), mam nadzieję że się uda.


--------------------
------
Per Aspera Ad Astra
Go to the top of the page
+Quote Post
Kasjan
post 14.10.2007, 18:05:10
Post #47





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 14.10.2007

Ostrzeżenie: (0%)
-----


witam, przepraszam ze odkopuje stare tematy, ale ten byl akurat na pierwszej stronie, a jego temat jest bardzo interesujacy.
mysle ze mozna bez problemu zorganizowac pluginy jednak trzymajac sie pewnego zalozenia: tworzymy swoj wlasny cms, i odgornie narzucamy mu konkretna strukture. tak np. modul news bedzie dzialal na zasadzie klasy, bedzie posiadal metody
- newsEdit
- newsDelete
- newsAdd
- newsDisplay
i tak, wewnatrz kazdej metody
Kod
public newsAdd() {
plugins::before('newsAdd');
// tutaj kod wlasciwy funkcji
plugins::after('newsAdd');
}


skad brac pluginy? funkcja plugins::after i plugins::before automatycznie przechwyci nazwe uruchamianego modulu (news) i automatycznie includuje wszystkie pliki w katalogu:
/modules/news/plugins/

struktura pluginu - oczywiscie klasa, nazwijmy go sobie newsRestrictedIPs:
/modules/news/plugins/RestrictedIPs.php

Kod
class newsRestrictedIPs {
public function onNewsAdd() {
   if ($_SERVER['REMOTE_ADDR'] == '5.10.15.20') {
    ....
  }
}
}

kwestia dogrania jak do klasy news wyslac info ze ma nie wstawiac obiektu... proponuje przed plugins::before('newsAdd'); dodac $settigns = array(); a w newsRestrictedIPs::onNewsAdd dodac $settings['dontInsert'] = true;

jeszcze dwa slowa odnosnie funkcji plugins::before i plugins::after - biora katalog
modules/NAZWA_MODULU/plugins/
includuja kolejno pliki, jesli zaincluduje to sprawdza cz istnieje [mod][nazwapliku]->on[nazwaakcji] czyli np. newsRestrictedIPs->onNewsAdd i uruchamia.

oczywiscie aby to wszystko dzialalo poprawnie musimy ustalic sobie pewne regoly jak pisac - nazewnictwo klas, metod, plikow... ale sa tego plusy - mamy w aplikacji porzadek...

jakies to rozwiazanie jest - czy dobre, czy zle - wypowiedzcie sie sami.


--------------------
pozdrawiam
Go to the top of the page
+Quote Post
NuLL
post 14.10.2007, 18:23:20
Post #48





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


A co jesli chcesz operowac na jakis danych zawartych w akcji ? Pozatym pisanie za kazdym razen metod plugins::before i after to raczej marne rozwiazanie.


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
LBO
post 14.10.2007, 18:41:39
Post #49





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


W większości przypadków wystarczają filtry, poparte dobrymi nawykami programistycznymi (interfejsy, dobrym dobraniem strategii etc.)
Go to the top of the page
+Quote Post
NuLL
post 14.10.2007, 18:45:55
Post #50





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


Filtry ? To ja myslalem ze filtry sluza do czego innego blink.gif ( czyt. filtrowania ) a plugin nie zawsze tylko czysci... Pozatym nawet gdyby - jak wywolac filtr na zmiennej zawartej w akcji ?

Ten post edytował NuLL 14.10.2007, 18:46:36


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
LBO
post 14.10.2007, 18:49:50
Post #51





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Nie czepiaj się, chodziło mi o powszechną implementacje Intercepting Filters w wielu, wielu frameworkach. Przykro mi, że nie zrozumiałeś.
Go to the top of the page
+Quote Post
Kasjan
post 14.10.2007, 22:23:11
Post #52





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 14.10.2007

Ostrzeżenie: (0%)
-----


Cytat(NuLL @ 14.10.2007, 18:23:20 ) *
A co jesli chcesz operowac na jakis danych zawartych w akcji ?


mam globalne obiekty $get i $post (lub $request) i tylko przez nie (zgodnie z narzucona sobie specyfikacja cms) moge sie odwolywac do $_GET i $_POST (lub $_REQUEST) i moge je edytowac przez plugin.

poza tym plugins::before i plugins::after mozna sobie zautomatyzowac - od czego mamy extends / mozna zrobic dekoratory


--------------------
pozdrawiam
Go to the top of the page
+Quote Post
Cysiaczek
post 15.10.2007, 07:48:05
Post #53





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Z mojego punktu widzenia to sa po prostu akcje przed i akcje po - niezależnie jak mądrze je nazwać ;p.
Takie rzeczy rozwiązuje sie moim zdaniem na poziomie frameworka, a nie CMS.

@Null - da się nawet taki bajer zobić, że możesz filtrować zmienne w akcji. Oczywiście nie lokalne zmienne metody, tylko zmienne, do których akcja się odwołuje. Z tego, co pamiętam, bo w swoim FW masz.
  1. <?php
  2. $this->post->zmienna;
  3. ?>

Jesteś w stanie przefiltrować zawartość danych POST pod kątem konkretnej akcji niejako z zewnątrz - bez jawnego wywołania kodu filtrujacego wewnątrz akcji, a zwyczajnie dodajac jakiś plik z informacją, co i jak ma zostać przefiltrowane.

Pozdrawiam.


--------------------
To think for yourself you must question authority and
learn how to put yourself in a state of vulnerable, open-mindedness;
chaotic, confused, vulnerability, to inform yourself.
Think for yourself. Question authority.
Go to the top of the page
+Quote Post
gamecreator
post 6.11.2007, 01:09:33
Post #54





Grupa: Zarejestrowani
Postów: 2
Pomógł: 0
Dołączył: 5.06.2003
Skąd: Żywiec

Ostrzeżenie: (0%)
-----


Najpierw trzeba by jedną rzecz doprecyzować:
wtyczki [plugins] i są rozszerzenia [extensions]. Rozszerzenia to rzecz trochę bardziej ogólna, bo pozwalają na różne sposoby rozszerzać kod główny: np. dodając nowe inlcudy, dziedzicząc klasy interfejsów, dodając pliki językowe, szablony, filtry itp. Wtyczki to pewien podzbiór rozszerzeń.

Pluginy to inaczej wtyczki.
A jeśli jest wtyczka, musi też być i gniazdko winksmiley.jpg
Gniazdkiem są tzw. "hooki" [haki? miejsca zaczepienia?], czyli przewidziane wcześniej miejsca w kodzie głównym, do których można podczepiać kod wtyczek. Tak więc jeśli chcemy mieć możliwość dołączania pluginów w skrypcie, to musimy od począku pisać skrypt pod tym kątem i zostawiać "hooki" dla wywołań pluginów w miejscach, gdzie przewidujemy jakieś możliwości rozszerzania. Jeśli piszemy w taki sposób, możemy łatwo dodawać pluginy, które podczepią się do tych miejsc i coś zrobią. Jednak kod główny [core] pozostanie niezmieniony.

@faster: Dobrze kombinujesz. Co do Twoich wątpliwości, jak można rozszerzyć działanie kodu głównego bez zmieniania go, odpowiedź jest prosta: polimorfizm. Jeśli kod główny jest napisany w taki sposób, by działał na ogólnych interfejsach, zamiast na konkretnych obiektach, można bardzo łatwo rozszerzyć system o nowe klasy, które będą pasować do wywołań tego głównego kodu i będą nadpisywać [nie dosłownie, lecz poprzez polimorfizm] jego funkcje. Hooki w stylu before() i after() to najprostszy przykład czegoś takiego. Większe możliwości daje jednak dziedziczenie i nadpisywanie metod interfejsów w klasach pochodnych [w innych językach zwie się to "funkcje wirtualne" lub "polimorficzne"].

Jeśli jednak chcemy zmieniać każdą możliwą część systemu, to system od podstaw musi być w taki sposób napisany, by wszystkie jego składniki były pluginami, a główny kod zajmowałby się jedynie ich ładowaniem i rejestrowaniem powiązań między nimi. To jest już trudniejsze do zrobienia [choć nie niemożliwe winksmiley.jpg] i wymaga dobrego przemyślenia. Może też być mniej wydajne, bo praktycznie wszelkie wywołania musiałyby być dispatchowane w tablicy zarejestrowanych usług.

I tu przyszedł mi do głowy jeszcze jeden problem: baza danych. Często jest tak, że pluginy także potrzebują przechowywać jakieś informacje w bazie danych. O ile dodanie dodatkowej tabeli z kluczami obcymi jeszcze jakoś da się w miarę łatwo zrobić z poziomu pluginu, o tyle już np. modyfikacja struktury istniejących tabel może być trudna, o ile wogóle ma to jakiś sens. Wie ktoś może, jak rozwiązywane jest dodawanie pluginów z rozszerzaniem struktury bazy danych? Bo aktualnie istniejące bazy danych są raczej mało "polimorficzne" ;J

P.S.: @nasty, @Athlan: Ale robicie byki, kupcie sobie słowniki ;P


--------------------
----
SasQ
Go to the top of the page
+Quote Post
deirathe
post 20.11.2007, 15:58:49
Post #55





Grupa: Zarejestrowani
Postów: 426
Pomógł: 32
Dołączył: 24.05.2007

Ostrzeżenie: (0%)
-----


skoro mowa o rozszerzeniach to czy widzicie jakieś bezpieczne sposoby na instalacje takowych rozszerzeń z poziomu użytkownika. Powiedzmy np że wchodzi do panelu w opcje rozszerzenia i sobie wyklikuje co mu tam potrzeba i voila.


--------------------
Kawałek mojego blogu
Everything should be as simple as possible but not simpler.
A Einstein
Go to the top of the page
+Quote Post
splatch
post 20.11.2007, 22:07:10
Post #56





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Pokusiłem się o wklepanie odrobiny kodu. Jest on niekompletny, aczkolwiek daje pogląd na całą sprawę od strony źródeł. Całość oparta mniej więcej stanowi wyciąg ze źródeł OSGi i Eclipse przepisany do PHP.

Definicja "paczki", części aplikacji
  1. <?php
  2. /**
  3.  * Paczka działająca w otoczeniu aplikacji. Obiekty tej klasy są tworzone
  4.  * przez framework a nie przez użytkownika. Nie musi on rozszeżać tej klasy
  5.  * jest ona tylko zestawem informacji co się dzieje w runtime.
  6.  *
  7.  * @author Łukasz Dywicki <luke@code-house.net>
  8.  */
  9. class Bundle {
  10.  
  11. /**
  12.  * Pobranie usług jakie chce używać i udostępniać paczka.
  13.  *
  14.  * @return object[] Lista usług, bez określonego interfejsu.
  15.  */
  16. function getRegisteredServices() {
  17. return array();
  18. }
  19.  
  20. /**
  21.  * Pobranie nagłówków z informacjami na temat paczki.
  22.  *
  23.  * @return Header Lista z unikalnymi nagłówkami.
  24.  */
  25. function getHeaders() {
  26. return array();
  27. }
  28.  
  29. /**
  30.  * Pobranie informacji o stanie paczki.
  31.  *
  32.  * @return stan paczki (któraś z wartości stałych z IState).
  33.  */
  34. function getState();
  35. }
  36.  
  37. ?>


Informacje o nagłówkach trzymane np w pliku .ini
  1. <?php
  2. /**
  3.  * Nagłówek z infomacjami na temat wymagań paczki.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. class Header {
  8.  
  9. /**
  10.  * Nazwa nagłówka.
  11.  * 
  12.  * @return string Najlepiej z zakresu stałych ISupportedHeaders.
  13.  */
  14. function getName() {}
  15.  
  16. /**
  17.  * Wartość nagłówka.
  18.  *
  19.  * @return string
  20.  */
  21. function getValue() {}
  22. }
  23.  
  24. /**
  25.  * Lista domyślnych nagłówków, jakie są domyślnie wspierane.
  26.  *
  27.  * @author Łukasz Dywicki <luke@code-house.net>
  28.  */
  29. interface ISupportedHeaders {
  30.  
  31. /**
  32.  * Nazwa nagłówka z informacjami o zależnościach paczki.
  33.  * W wymaganiach można podać również wersję w jakiej paczka
  34.  * powinna występować. Brak informacji o wersji oznacza, że
  35.  * paczka współpracuje z dowolną wersją.
  36.  *
  37.  * require-bundle = pl.dywicki.db: 0.5, pl.dywicki.view: 1.1
  38.  */
  39. const REQUIRE_BUNDLES = "require-bundle";
  40.  
  41. /**
  42.  * Informacje o dostawcy paczki.
  43.  *
  44.  * vendor-name = Łukasz Dywicki
  45.  * vendor-url = <a href=\"http://dywicki.pl\" target=\"_blank\">http://dywicki.pl</a>
  46.  * vendor-organization = Code-House.org
  47.  */
  48. const VENDOR_NAME = "vendor-name";
  49. const VENDOR_URL = "vendor-url";
  50. const VENDOR_ORGANIZATION = "vendor-organization";
  51.  
  52. /**
  53.  * Informacje o paczce.
  54.  * 
  55.  * bundle-name = pl.dywicki.view.explorer
  56.  * bundle-version = 0.5.13
  57.  */
  58. const BUNDLE_NAME = "bundle-name";
  59. const BUNDLE_VERSION = "bundle-version";
  60.  
  61. }
  62.  
  63. ?>



Kontekst w jakim działa aplikacja, chodzi tu głównie o warstwę usług a nie request response etc.
  1. <?php
  2. /**
  3.  * Kontekst działania rozszeżenia.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. interface IBundleContext {
  8.  
  9. /**
  10.  * Pobranie jakiejś usługi.
  11.  *
  12.  * @return object Interfejs nie jest określony
  13.  */
  14. function getServices();
  15.  
  16. // Fragment z listenerami do propagacji informacji.
  17. function addFrameworkListener(IFrameworkListener $listener);
  18. function removeFrameworkListener(IFrameworkListener $listener);
  19. function addBundleListener(IBundleListener $listener);
  20. function removeBundleListener(IBundleListener $listener);
  21. }
  22. ?>


Definicja pluginu - jedyne co od niego wymagamy to start i stop, opcjonalnie install, uninstall.
  1. <?php
  2. /**
  3.  * Rozszeżenie jakiegoś extension pointa.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. interface IPlugin {
  8.  
  9. /**
  10.  * Uruchomienie pluginu.
  11.  *
  12.  * @param $context Kontekst w jakim działa plugin.
  13.  */
  14. function start(IBundleContext $context);
  15.  
  16. /**
  17.  * Zatrzymanie pluginu
  18.  *
  19.  * @param $context Kontekts, w którym działał plugin.
  20.  */
  21. function stop(IBundleContext $context);
  22. }
  23. ?>


Warunki dla pluginów
  1. <?php
  2. /**
  3.  * Interfejs reprezentujący warunek, jaki powinien spełniać plugin.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net> 
  6.  */
  7. interface ICriteria {
  8.  
  9. /**
  10.  * Sprawdzenie czy plugin jest "ok".
  11.  *
  12.  * @param $plugin Implementacja rozszeżenia.
  13.  */
  14. function isValid(IPlugin $plugin);
  15.  
  16. }
  17.  
  18. // przykładowa implementacja
  19. class InstanceOfCriteria implements ICriteria {
  20.  
  21. public function __construct(string $name) {
  22. $this->interfaceName = $name;
  23. }
  24.  
  25. function isValid(IPlugin $plugin) {
  26. return ($plugin instanceof $this->interfaceName);
  27. }
  28. }
  29.  
  30. ?>


Hook = extension point - czyli miejsce, w którym ktoś się wpina przez pluginy
  1. <?php
  2. /**
  3.  * Definicja nowego EP.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. interface IExtensionPoint {
  8.  
  9. /**
  10.  * Nazwa EP (opcjonalna).
  11.  *
  12.  * @return string.
  13.  */
  14. function getName();
  15.  
  16. /**
  17.  * Identyfikator EP (obowiązkowy)
  18.  *
  19.  * @return Unikalny identyfikator EP.
  20.  */
  21. function getExtensionPointId();
  22.  
  23. /**
  24.  * Warunki, jakie muszą spełnić pluginy, by być uznane
  25.  * za poprawne rozszeżenia danego EP.
  26.  *
  27.  * @return ICriteria[] Lista warunków.
  28.  */
  29. function getCriteria();
  30.  
  31. }
  32.  
  33.  
  34. ?>


Rejestr rozszerzeń - czyli coś, w czym wszystkie EP są dodawane, usuwane i przetrzymywane.
  1. <?php
  2. /**
  3.  * Centralny rejestr trzymający listę extension pointów.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. interface IExtensionRegistry {
  8.  
  9. /**
  10.  * Dodanie nowej definicji EP do rejestru.
  11.  *
  12.  * @param $point 
  13.  */
  14. function registerExtensionPoint(IExtensionPoint $point);
  15.  
  16. /**
  17.  * Pobranie EP o danym identyfikatorze.
  18.  *
  19.  * @param $namespace Przestrzeń nazw rozszeżenia (np. pl.dywicki.content)
  20.  * @return IExtensionPoint
  21.  */
  22. function getExtensionPoint(string $namespace);
  23.  
  24. /**
  25.  * Pobranie listy wszystkich EP.
  26.  *
  27.  * @return IExtensionPoint[] Tablica zawierająca EP.
  28.  */
  29. function getExtensionPoints();
  30.  
  31. /**
  32.  * Dodanie listenera nasłuchującego zmian.
  33.  *
  34.  * @param $listener Ktoś, kto chce dużo wiedzieć.
  35.  */
  36. function addRegistryListener(IRegistryListener $listener);
  37.  
  38. /**
  39.  * Usunięcie listenera, który obserwuje zmiany w rejestrze.
  40.  *
  41.  * @param $listener Ktoś, kto już nie chce chce dużo wiedzieć.
  42.  */
  43. function removeRegistryListener(IRegistryListener $listener);
  44. }
  45. ?>


Stany, w jakich może być paczka (paczka != plugin)
  1. <?php
  2. /**
  3.  * Interfejs reprezentujący stan paczki.
  4.  *
  5.  * @author Łukasz Dywicki <luke@code-house.net>
  6.  */
  7. interface IState {
  8.  
  9. /**
  10.  * Paczka zainstalowana.
  11.  */
  12. const INSTALLED = 0x01;
  13.  
  14. /**
  15.  * Paczka niezainstalowana.
  16.  */
  17. const UNINSTALLED = 0x02;
  18.  
  19. /**
  20.  * Paczka w fazie uruchamiania.
  21.  */
  22. const ACTIVATING = 1;
  23.  
  24. /**
  25.  * Paczka uruchomiona.
  26.  */
  27. const ACTIVE = 2;
  28.  
  29. /**
  30.  * Paczka zatrzymana.
  31.  */
  32. const STOPED = 3;
  33.  
  34. /**
  35.  * Paczka podczas zatrzymywania.
  36.  */
  37. const STOPPING = 4;
  38.  
  39. }
  40.  
  41. ?>


--------------------
Łukasz Dywicki
Independent Java and open source software consultant.
Blog - Java, OSGi, integracja oprogramowania..
Go to the top of the page
+Quote Post
Babcia@Stefa
post 5.03.2008, 12:17:15
Post #57





Grupa: Zarejestrowani
Postów: 654
Pomógł: 17
Dołączył: 19.03.2006
Skąd: z kosmosu ;)

Ostrzeżenie: (0%)
-----


Moje rozwiązanie jest takie:

Archiwum (np. rar, zip itp.) {
- plik 1
- plik 2
- plik 3
- info.xml
}

Info.xml
  1. <?xml version="1.0"?>
  2. <plugin>
  3. <folders>
  4. <create folder="nazwa folderu"/>
  5. </folders>
  6. <menu>
  7. <menu key="xD" link="page,testplugin"/>
  8. </menu>
  9. <files>
  10. <file unpack="ścieżka wyjściowa" name="nazwa z archiwum"/>
  11. </files>
  12. </files>
  13. </plugin>


Jest ono bardzo proste ;]

Pozdrawiam, Babcia@Stefa


--------------------
Środowisko testowe (desktop) - Gedit, lighttpd, sftp, rsync, xfce4-terminal, chromium, firefox4 | System: Gentoo ~x86
O'Neill - serwer WWW @ lighttpd, links, nano, rsyncd, sftpd | System: Debian
Go to the top of the page
+Quote Post
NuLL
post 7.03.2008, 16:37:31
Post #58





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


@splatch - myslisz ze daloby sie to wykorzystac w PHP ? Zastanawiam sie jaki narzut kodu i czasu wynikalby z takiego rozwiazania smile.gif Dzieki za ten kod - mi ciezko by bylo to wyciagnac a myslalem o tym ostatnio. Zastanawiam sie nad napisaniem jakies prostej aplikacji z tego korzystajacej - ale zobaczymy jak z czasem i czy wogole sie uda winksmiley.jpg


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
specialplan
post 11.03.2008, 16:52:28
Post #59





Grupa: Zarejestrowani
Postów: 206
Pomógł: 21
Dołączył: 1.09.2006
Skąd: Edinburgh

Ostrzeżenie: (0%)
-----


Podepne sie, by nie zakladac nowego tematu.

Od jakiegos czasu pracuje nad systemem pluginow. W CMS, nad ktorym obecnie spedzam wiele godzin w pracy, poprzez plugin rozumie sie klase (lub ich zbior) odpowiedzialna za jakies dodatkowe, doinstalowalne funkcje (np system newsow, ktory mozna doinstalowac do zrodla i jego funkcjonalnosci beda dostepne w calym silniku). Mam juz dzialajacy instalator i ogolna obsluge takich paczek (usuwanie, aktywowanie, deaktywowanie, startowanie, restartowanie itd). Nie bede sie w to teraz zaglebial...

Stanalem jednak na rozdrozu, jesli chodzi o rejestr funkcjonalnosci. Zalozmy, ze klasa news zawiera kilka metod publicznych, jak np addNews, deleteNews, modifyNews, displayNews itd itp. Jednym z rozwiazan, na jakie wpadlem jest stworzenie z pomoca Reflection API rejestru metod publicznych, ktore dany plugin udostepnia i operowanie na nich w dowolnym miejscu systemu (Factory, Autoloading itd). Czyli rejestruje sobie moje funkcjonalnosci i pozniej, np w warstwie widoku tylko odwoluje sie do danej metody, np PluginManager::dispatch(nazwaPluginu, zarejestrowanaFunkcjonalnosc, argumenty) (to taki luzny bardzo przyklad). Mysle, ze to calkiem wygodne.

Moj PM wpadl jednak na karkolomny pomysl zdynamizowania zarejestrowanych uslug. Chodzi mu po glowie, by w panelu administracyjnym, gdzie wylistowane sa dostepne w rejestrze uslugi, po kliknieciu na dana nazwe metody dla danego pluginu od razu mozna bylo z tego miejsca go obsluzyc. Nie za bardzo wiem jak sie do tego dobrac, poniewaz musialoby to byc super-uniwersalne, jako ze dodawanie newsow rozni sie, powiedzmy od wyswietlenia lokacji na wtyczce Google Maps;] Spedzam drugi dzien na probie rozplanowania jakiegos Buildera formularzy, jednak co chwila wychodza jakies problemy zwiazane z uniwersalizacja takiego systemu.

Probowalem jakies diagramy UML na Decoratorze rozrysowywac, jednak jak dla mnie to ciagle za ogolne dzialanie, by to objac jakos sensownie bez miliona linijek kodu ;]

Jesli ktos rozumie, o co mi chodzi, to moze jakies pomysly wpadna do glowy?:_)

Ten post edytował specialplan 11.03.2008, 16:55:36
Go to the top of the page
+Quote Post
carbolymer
post 11.03.2008, 23:30:17
Post #60





Grupa: Zarejestrowani
Postów: 102
Pomógł: 12
Dołączył: 27.01.2007
Skąd: north              Poziom: 158                     Tytuł: Miszcz

Ostrzeżenie: (0%)
-----


Jakiś czas temu naskrobałem sobie nawet dobry plugin system. Jego mechanika działania wygląda tak:
Jest aplikacja PHP zbudowana z kilku-kilkunastu klas.
Jest klasa Matrix - klasa bazowa, z której powinny dziedziczyć te klasy, w których mogły by się wczepiać pluginy.
Jej działanie jest takie: przed (on[nazwaklasy]_pre_[nazwafunkcji]) i po (on[nazwaklasy]_post_[nazwafunkcji]) wywołaniem metody jednej z klas aplikacji jest wywoływana metoda pluginu (metoda pre musi mieć zgodną liczbę argumentów co do funkcjiobsługiwanej - metoda post przyjmuje tylko 1 argument, wartość zwracaną przez funkcję obsługiwaną) o odpowiedniej nazwie która ma możliwość modyfikowania argumentów i wyniku funkcji.
Każda metoda która "chce" być obsługiwana przez pluginy powinna być protected lub private i zaczynać się od _ np.:
  1. <?php
  2. class foo extends Matrix
  3. {
  4.  
  5. //metoda koniecznie protected lub private poprzedzone '_'
  6. protected function _test($val)
  7. {
  8. echo '<br/>Test val:'.$val.'<br/>';
  9. }
  10.  
  11. }
  12. ?>

Potem przy starcie aplikacji poprostu tworzymy obiekt klasy foo, ładujemy (dziedziczoną metodą z Matrix) plugin - można by zeskanować katalog lub konfig na starcie.
  1. <?php
  2. $bar = new foo();
  3. $bar->loadPlugin('test'); // ładujemy plugin, można załadować tylko raz!
  4. $bar->test(123); // wywołanie metody klasy foo, a zarazem odpowiednich metod pluginu
  5. ?>


Kod w całości:
http://carbolymer.ovh.org/wp/?p=18


--------------------
Blog | plugin system by carbolymer
Residence: #php.pl @ IRCNet
"Pralki powstały po to, aby kobiety też mogły programować"
Go to the top of the page
+Quote Post

5 Stron V  < 1 2 3 4 5 >
Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.03.2024 - 10:30