Plugin – wielokrotne wykorzystanie sprawdzonych narzędzi
Tworzenie aplikacji, składa się zarówno z tych bardziej twórczych, jak i bardziej odtwórczych prac. Mimo wszelkich naszych starań tworzenia wedle zasady DRY (z ang. DRY – Don’t Repeat Yourself ), ile razy zdarza się, że dla tej samej funkcjonalności powielamy i dostosowujemy ten sam kod w różnych elementach aplikacji lub pomiędzy różnymi aplikacjami.
Autor: Piotr Plenik
Źródło: Software Developer’s Journal 11/2008 (167) http://sdjournal.org
Dowiesz się:
- Efektywnie wykorzystywać pluginy w swojej pracy;
- Stworzyć własny plugin;
- Wykorzystywać istniejące pluginy to szybkiego tworzenia aplikacji.
Powinieneś wiedzieć:
- Jak stworzyć projekt w symfony;
- Posiadać doświadczenie w tworzeniu aplikacji;
- Posiadać doświadczenie w obiektowym PHP
Poziom trudności 1
Na początek zaprezentuję najczęściej wykorzystywane pluginy w Symfony, których jest w chwili pisania artykułu ponad 200. Następnie stworzymy prosty dodatek do wysyłania maila (ang. plugin) w symfony, bez dodatkowego nakładu naszej pracy.
Pluginy w Symfony
W Symfony jeden z największych walorów możemy odnaleźć w liczbie i różnorodności pluginów. Obecnie z ponad 200 pluginów możemy np. szybko stworzyć prosty CMS, Blog czy Forum, podłączyć do naszej aplikacji bezpieczny mechanizm autoryzacji i autentyfikacji sfGuardPlugin, czy łatwo podczepić AJAXowe biblioteki. Wszystkie z nich tworzone są bezpłatnie przez społeczność Symfony i znajdziemy je na stronie: http://www.symfony-project.org/plugins/ Każdy plugin posiada dostępny kod źródłowy, który budowany jest zgodnie z przyjętą w Symfony strukturą, dzięki czemu łatwo się nam w nim odnaleźć. Wśród dostępnych pluginów można między innymi znaleźć:
- sfSimpleCMSPlugin – prosty CMS do zarządzania treścią i strukturą strony;
- sfGuardPlugin – autoryzacja i zarządzanie użytkownikami oraz uprawnieniami;
- sfThumbnailPlugin – tworzenie miniaturek zdjęć;
- sfControlPanelPlugin – interfejs do zarządzania Symfony z poziomu przeglądarki;
- sfLightboxPlugin – łatwe wykorzystywanie skryptu AJAX-owego Lightbox2;
- sfSslRequirementPlugin – wprowadzenie kodowania SSL dla akcji;
- sfPropelActAsNestedSetBehaviorPlugin – wdrożenie algorytmu nested set zintegrowanego z obiektami Propela;
- sfPokaYoke – walidacja formularzy po stronie klienta.
Zmiany warto śledzić na bieżąco, gdyż pluginy cały czas są tworzone i rozwijane. Przy korzystaniu z projektów, warto jest zainteresować się licencją, zgodnie z którą jest wydawany plugin. Licencję pluginu można znaleźć na stronie pluginu na http://symfony-project. com oraz w głównym katalogu pluginu, w pliku LICENSE. Zdecydowana większość z nich jest wydawana na licencji MIT, tak jak i samo symfony, w związku z czym bez przeszkód możemy je wykorzystywać również w celach komercyjnych.
Listing 1. Struktura plików pluginu
nazwaPluginu/
config/
*schema.yml # plik ze schematem bazy danych
config.php # specyficzna konfiguracja dla pluginu
data/
generator/
sfPropelAdmin/
nazwaSzablonu/ # skórka dla admin generatora
template/
skeleton/
fixtures/
*.yml # testowe informacji do bazy danych
lib/
*.php # miejsce na nasze klasy
helper/
*.php # pomocniki
model/
*.php # model danych, generowany z propela
task/
Task.class.php # zadania do uruchomienia w pasku komend
modules/
nazwaModulu/ # nazwa tworzonego modułu
actions/
config/
module.yml
view.yml
security.yml
templates:
*.php
validate:
*.yml
————————————————————————-
Listing 2. Przykład wykorzystania konfiguracji w pliku config.php
$r = sfRouting::getInstance(); // pobranie instancji odpowiedzialnej
za przekierowania
$r->prependRoute(‘submit’, ‘/wyslij’,
array(
‘module’ => ‘sfMailForm’,
‘action’ => ‘submit’)
); // dopisanie czytelniejszego adresu
// z /sfMailForm/submit na /wyslij
————————————————————————-
Listing 3. Przykładowa schema.yml z encją gromadzącą informacje z wprowadzonych danych z
formularzy
propel:
_attributes: { package: plugins.sfMailFormPlugin.lib.model }
# deklaracja informacji o pakiecie (miejscu zapisu
klas pluginu)
sfMailForm_archive:
attributes: { phpName: pluginMailForm }
id:
content: { type: longvarchar }
created_at:
Instalacja pluginu
Najczęściej pluginy wymienione na Symfony Plugins zostały przygotowane jako paczki PEAR, dlatego możemy je zainstalować, podając w Symfony 1.0 polecenie: <cd mojprojekt <symfony plugin-install nazwapluginu lub w wersji 1.1: <cd mojprojekt <symfony plugin:install nazwapluginu Dokładną informację, jak należy zainstalować potrzebny plugin do określonej wersji Symfony, możemy podejrzeć na stronie pluginu, w zakładce Installation.
Rozpoczęcie pracy
Do rozpoczęcia pracy potrzebujemy oczywiście utworzonego projektu Symfony. Poszczególne kroki tworzenia projektu dokładnie przedstawiliśmy na początku prezentacji multimedialnej. Jak stworzyć plugin, zaprezentowaliśmy na płycie dołączonej do Software Developer’s Journal 7/2008. W związku z tym, że sam plugin był tworzony ponad pół roku temu, niektóre wykorzystane w nim techniki są już wycofywane. Aby nasz plugin był zgodny z symfony 1.0 należy włączyć parametr compat_10 w pliku konfiguracyjnym config/settings.yml naszej aplikacji. Jest tam również kod źródłowy pluginu. Poniżej omówimy zawartość płyty oraz pokażemy, w jaki sposób można ją rozbudowywać.
Struktura pluginu
Sporym ułatwieniem jest, zorganizowanie struktury katalogów i plików pluginu, w bardzo podobny sposób co struktura naszej aplikacji. Dzięki temu bez problemu możemy odnaleźć się w jego zawartości. Łatwo jest również przenieść istniejącego moduł w naszej aplikacji, aby funkcjonował jako osobny moduł. Struktura plików przedstawiona została na Listingu 1. Pamiętaj – aby po każdej zmianie struktury pluginu zalecane jest czyszczenie cache projektu komendą symfony cc. Postaramy się przedstawić najważniejsze elementy struktury i podać przykłady informacji, jakie można w nich zawrzeć.
Listing 4. Przykładowa budowa zadania mailform-raport
<?php
/**
* Raport o statystykach wypełniania formularza
* plik: /plugins/sfMailFormPlugin/data/tasks/sfMailFormRaport.php
*//
pake_desc(‘raport o statystykach do administratora – przeslanie na adres e-mail’);
pake_task(‘mailform-report’, ‘project_exists’);
pake_alias(‘mailreport’, ‘mailform-report’); // możliwość używania skrótu „mailreport”
/**
* Funkcja wywoływana przy uruchomieniu zadania
* @param pakeTask $task
* @param Array $args
*/
function run_mailform-report($task, $args)
{
if (!count($args))
{
throw new Exception(‘Podaj proszę adres e-mail, na który ma przyjść raport’);
}
$emial = $args[0];
// …
// miejsce na kod wyciągający dane z bazy i wysyłający mail z raportem
// ..
}
Moduły
Moduły umieszczamy w katalogu modules/. Nasz prezentacyjny plugin posiada moduł (ang. Modules) sfMailForm. W zależności od potrzeby, każdy moduł może zawierać cztery katalogi:
- actions – definiujący dostępne akcje dla modułu;
- config – określający specyficzną konfigurację samego modułu;
- templates – widoki dla modułów zwracane po wywołaniu akcji;
- validate – formularze sprawdzania wprowadzanych danych przez formularze.
W praktyce przyjęło się tworzenie dodatkowego katalogu lib/, zawierającego klasę z wszystkimi akcjami (Listing 1). W pliku actions.class.php pozostawia się jedynie rozszerzenie do klasy z katalogu lib/ (Listing 2). Takie rozwiązanie zostało zastosowane w przykładowym pluginie.
Konfiguracja pluginu
Konfigurację dla pluginu definiujemy config/ w katalogu pluginu. Może ona składać się z dwóch elementów:
- konfiguracji dla naszego pluginu – plik config.php;
- struktury bazy danych – plik schema.xml lub schema.yml.
W pliku konfiguracyjnym config.php możemy elastycznie odwoływać się do konfiguracji naszej aplikacji i dowolnie dopisywać lub modyfikować wprowadzone wartości. Przykładowo możemy stworzyć przyjaźniejszy adres wysyłania formularza na /wyslij zamiast / sfmailForm/submit (przykład na Listingu 2). W pliku definicji struktury bazy danych (plik schema.yml lub schema.xml) tworzymy konfigurację – podobnie jak w całym projekcie. Wyjątkiem jest zawarcie w pliku informacji o pakiecie (przykład na Listingu 3). Stworzona schema będzie bez problemu wykrywana przez wywoływanie komendy z prefiksem propel. Na Listingu 3 znajduje się przykład pliku schema.yml, zawierający tabelę sfMailform_ archive, która będzie zapisywać dane wprowadzone w naszym przykładowym formularzu. Po skonfigurowaniu pliku czeka nas jeszcze tylko dobre skonfigurowanie pliku databases. yml w naszym projekcie oraz budowa modelu Propela, SQL-a i stworzenie struktury w bazie danych (np. za jednym zamachem komendą symfony propel-build-all).
Dane do testów (fixtures)
Dane do testów umieszczamy w plugine w katalogu data/fixtures/. Wywoływanie ładowania danych wykonujemy komendą symfony propel-load-data. Zawieramy tutaj dane, które chcielibyśmy umieścić w bazie danych, tak aby nasz plugin działał poprawnie.
Zadania do uruchomienia z linii komend
Nowe zadania (ang. Tasks) tworzone w pluginie zawieramy w katalogu data/tasks/. Każde zadanie umieszczamy w oddzielnym pliku, który powinien zawierać wywołanie funkcji pake_desc oraz pake_task, a także funkcję wywołującą zadanie (zainteresowanych odsyłam do Listingu 4).
Tworzenienie pluginu jako paczki PEAR
Aby nasz plugin można było instalować za pomocą komendy symfony plugin:install musi on mieć zdefiniowany w głównym katalogu plik package. xml. Plik ten zawiera w odpowiednio przygotowanym formacie XML-owym wszystkie potrzebne informacje o pluginie. Opiszę wszystkie możliwe do zastosowania znaczniki wraz z przykładowymi wartościami dla naszego pakietu.
Możliwe znaczniki
Główny znacznik w pliku package.xml zawiera <?xml version=”1.0″ encoding=”UTF-8″?>, a pod nim mamy informację o pakiecie: <package packagerversion=”1.4.1″ version=”2.0″ xmlns=”http://pear.php.net/ dtd/package-2.0″ xmlns:tasks=”http: //pear.php.net/dtd/tasks-1.0″ xmlns: xsi=”http://www.w3.org/2001/XMLSchemainstance” xsi:schemaLocation=”http: //pear.php.net/dtd/tasks-1.0 http:// pear.php.net/dtd/tasks-1.0.xsd http: //pear.php.net/dtd/package-2.0 http:// pear.php.net/dtd/package-2.0.xsd”>. Z elementów poniżej mamy:
- <name>: nazwa pluginu; w naszym przypadku: sfMailFormPlugin;
- <channel>: informacja na jakim serwerze znajduje się paczka (w przypadku paczek dostępnych na symfony-project.org, będzie to: plugins.symfony-project.org);
- <summary>: krótki opis o samym pluginie;
- <description>: dłuższy opis;
- <lead>: informacja o liderze projektu:
- <name>: imię i nazwisko;
- <user>: nazwa użytkownika (w przypadku gdy jest to projekt na symfonyproject. org, będzie to login do zarządzania projektami);
- <email>: poprawny adres e-mail lidera;
- <active>: informacja czy osoba nadal pracuje nad tym projektem (wartości: yes lub no);
- <date>: data ostatniej poprawki w paczce (np.: 2008-12-31);
- <time>: czas ostatniej poprawki w paczce (np.: 23:59:00);
- <version>: informacje o wydanej wersji:
- <release> i <api>: numer wydania;
- <stability>: informacja o stabilności wydania;
- <release> i <api>: słowna informacja o stabilności (np. stable, beta, alpha);
- <license uri=”xxx”>: informacja o nazwie licencji wraz z odesłaniem do strony z jej treścią podawaną w atrybucie uri;
- <notes>: miejsce na dodatkowe komentarze;
- <contents>: lista zamieszczonych plików:
- <dir name=”xxx”>: nazwa katalogu podawana w atrybucie name;
- <file role=”data” name=”xxx”>: nazwa pliku (atrybut name);
- <dependencies>: zależności występujące przy naszej paczce:
- <php>: zależność od wersji PHP (np. ze znacznikiem <min>5.2.0</ min>, umożlwi instalację, gdy na ser werze znajdować będzie się wersja 5.2.0 lub wyższa);
- <pearinstaller>: zależność od wersji PEAR;
- <package>: zależność od innych paczek symfony:
- <name>: nazwa paczki;
- <channel>: informacja o ser werze, na którym paczka się znajduje;
- <min>: minimalna wersja paczki;
- <max>: maksymalna wersja paczki;
O autorze
Współzałożyciel firmy TeamLab.pl, specjalizującej się w wytwarzaniu oprogramowania klasy enterprise. Zawodowo zajmujący się tworzeniem oraz rozwojem aplikacji dla biznesu, typu CMS i CRM. W wolnym czasie redaktor serwisu www.symfony. pl. W PHP programuje 2000 r., w frameworku symfony od 2006 r.. Administrator portalu dla Organizacji Pozarządowych – www.ngo.pl. Absolwent ostatniego roku Polsko-Japońskiej Wyższej Szkoły Technik Komputerowych. Interesuje się zarządzaniem projektami biznesowymi oraz open source, programowanie (PHP, ASP.NET, Java) oraz bazy danych (MS SQL, PostgreSQL, MySQL).
Kontakt z autorem: piotr.plenik@teamlab.pl



















