Symfony 2 wydane

30 lipca 2011

Tuż po tym jak zabrałem się za naukę Zend Framework chciałem także sięgnąć po Symfony. Odłożyłem to jednak na później bo o ile o Zend Framework 2 jeszcze niewiele było słychać (i to się na razie nie zmienia) o tyle Symfony 2 rozwijało się już od wielu miesięcy. Wolałem więc poczekać z nauką na stabilną wersję 2.0. I doczekałem się :)

28 lipca Fabien Potencier, ojciec projektu, wykonał commit do repozytorium Git i tym samym nastał oficjalny początek pierwszej stabilnej wersji Symfony 2. Na nowej stronie projektu możecie przeczytać jak sam opisuje cechy najnowszej wersji swojego frameworka.

Nie programowałem w Symfony 1 więc nie wiem co jest zupełną nowością a co zostało tylko poprawione i w jakim stopniu. Jest jednak kilka rzeczy przez które mam wielkie nadzieje co do tego oprogramowania. Oto one:

  • Symfony 2 składa się z (powiązanych ze sobą ale jednak oddzielnych) pakietów. Nawet jeżeli nie programujesz w Symfony to możesz wykorzystać konkretne moduły w swoich aplikacjach. Przypomina mi to ideę Zend Framework i bardzo mi się to podoba.
  • Aby móc korzystać z nowego frameworka potrzebne jest PHP w wersji co najmniej 5.3.2. Mam nadzieję, że to wymusi na dostawcach hostingu szybsze wprowadzenie na swoje serwery PHP 5.3. Wydano je 30 czerwca 2009 roku a do tej pory znaczna część hostingodawców (większość?) jej nie udostępnia! Dzięki nowemu Symfony wreszcie mam pretekst aby dobrze poznać przestrzenie nazw.
  • Kod naszej aplikacji w Symfony 2 może dzielić się na pakiety (bundles). To bardzo ekscytująca nowość. W skład takiego pakietu może wchodzić kod PHP, HTML, JavaScipt, pliki graficzne itd. czyli wszystko czego potrzebujemy do uruchomienia samodzielnego elementu naszej strony np. forum, blog czy system newsów. Przypomina mi to trochę moduły/pluginy z CMS’ów ale pisane wreszcie na podstawie dojrzałego oprogramowania i według jasnych, przejrzystych zasad. Ułatwi to również pracę w zespole nad dużymi projektami. Zobaczymy jak to się sprawdza w praktyce :)

To trzy główne nowości, które dla mnie są najważniejsze. Na tym oczywiście nie koniec ale tu odnoszę już do strony projektu i krótkiego wprowadzenia do nowego Symfony. Osoby zaznajomione z poprzednią wersją frameworka powinny również zainteresować się artykułem o różnicach między wersjami.

Kończę bo czeka na mnie jeszcze gorąca, nowa instalacja Symfony 2 :) Swój najnowszy projekt chcę oprzeć właśnie o ten framework.

PS
Jeżeli chcesz zacząć zabawę z Symfony 2 to zalecam pobrać paczkę .zip a nie .tgz. Z jakiegoś niewyjaśnionego powodu paczka .tgz ma błędy.. Wszystko się normalnie rozpakowuje ale parser PHP sypie błędami, pliki z kodem mają czasami rozszerzenie .ph zamiast .php i cholera wie co jeszcze tam jest nie tak :) Co jeszcze dziwniejsze, ten problem pojawia się nie pierwszy raz. Tak samo bywało z poprzednimi wersjami RC, beta itd. Takie rzeczy nie powinny mieć miejsca…


Praca zdalna

30 czerwca 2011

Jedna z moich niedawnych rozmów zmotywowała mnie aby wreszcie opisać jak wygląda praca zdalna, z mojego punktu widzenia. Od kilku lat pracuję tylko zdalnie. W różnych firmach, w różnej formie ale zawsze w domu.

Niektórym osobom tryb pracy zdalnej jawi się jako brama do raju. Takie beztroskie myślenie towarzyszy większości moich znajomych. Rzeczywistość wygląda trochę inaczej i należy przeprowadzić naprawdę konkretną i bezkompromisową analizę żeby móc wyciągać wnioski.

Chciałbym opisać tryb pracy zdalnej zarówno z punktu widzenia pracownika jak i pracodawcy. Dodatkowo, część będzie dotyczyła momentu poszukiwania pracy/pracownika a część już samej pracy. Posłuży mi do tego wszystkiego dość luźna forma listy zalet i wad. Myślę, że bez względu na to kim jesteś (pracownik czy pracodawca) warto chyba przeczytać całość żeby być w pełni świadomym z czym mamy do czynienia.

Tekst dotyczy zdalnej pracy programisty/webdevelopera w sytuacji gdy istnieje zespół stacjonarny, pracujący na miejscu. Trochę inaczej wygląda sytuacja gdy wszyscy pracują zdalnie, jeszcze inaczej gdy mamy do czynienia z innym zawodem np. tłumacz. Jestem pewien, że poradzisz sobie z przefiltrowaniem moich wskazówek pod kątem własnej, konkretnej sytuacji :)

Z punktu widzenia pracownika

Zalety

  • Większy wybór pracodawców a więc większa szansa znalezienia pracy. Co prawda, ofert pracy zdalnej nie jest zatrzęsienie ale każda z nich to i tak o jedną więcej niż to co masz na miejscu. Jeżeli w Twojej okolicy nie ma dla Ciebie pracy i pozostaje tylko praca zdalna lub przeprowadzka to tym bardziej docenisz taką formę zatrudnienia.
  • Oszczędność czasu, pieniędzy i nerwów na dotarcie do pracy, przebicie się przez korki itd.
  • Jeżeli mieszkasz w Pacanowie a zarabiasz w Warszawie to jest to dla Ciebie atrakcyjny układ, masz mniejsze koszty utrzymania, w Twojej kieszeni zostaje więcej pieniędzy.
  • Możesz się obudzić pięć minut przed rozpoczęciem pracy i nikt nie będzie miał o to pretensji. Lepiej jednak nie praktykować tego stale, praca w kapciach i szlafroku rozleniwia. Im bardziej poczujesz, że „idziesz” do pracy tym lepiej dla Ciebie i pracodawcy.
  • Łatwiej Ci podjąć pracę jeżeli masz kłopoty ze zdrowiem.

Wady

  • Istnieje bardzo poważne zagrożenie, że nigdy nie staniesz się pełnoprawnym członkiem zespołu jeżeli tylko część pracowników jest pracownikami zdalnymi. Zagrożenie to wzrasta wraz ze wzrostem liczby pracowników stacjonarnych i/lub spadkiem liczby pracowników zdalnych.
  • Pracodawcy trudno jest kontrolować Twój czas pracy. Nie widzi Cię, nie może zobaczyć, że siedzisz nad kodem. W takiej sytuacji każde Twoje wyjście do WC, każda przerwa na obiad itd. jest wyraźniej widoczna niż ma to miejsce w biurze. Jesteś oceniany i pilnowany tylko na podstawie zegarka, Twoje przerwy wydłużają się dla szefa w nieskończoność i nie ma miejsca na poranną kawkę i ploteczki.
  • W związku z powyższym, nie każdy pracodawca potrafi się uporać z fałszywą sugestią, że robisz mniej. Będą kłopoty.
  • Musisz być bardziej samodzielny, lepiej radzić sobie z problemami itd. niż inni. Łatwo poprosić o radę kolegę z biurka obok, trudniej komuś marudzić co jakiś czas na Skype.
  • Swoje rachunki za prąd płacisz Ty, nie pracodawca :)
  • Najprawdopodobniej będziesz pracował na swoim sprzęcie i to Ty poczujesz ubytek w kieszeni gdy coś się zepsuje.
  • Każda inna awaria (np. brak prądu) będzie także Twoim problemem.
  • Musisz sobie zorganizować stanowisko pracy. Zapomnij o pracy na kanapie z laptopem na kolanach. Idealnym rozwiązaniem jest wydzielenie sobie kącika albo nawet całego małego pokoju tylko do pracy. Ja tak zrobiłem :)
  • Twoi współlokatorzy będą od Ciebie oczekiwać, że poodkurzasz, pozmywasz i wyprowadzisz psa na spacer. Jak odmówisz to powiedzą żeś leń. Daj im do zrozumienia, że do 16 (17 czy do którejś tam) jesteś w pracy, nie w domu.
  • Bardzo trudno oddzielić życie prywatne od pracy.
  • Bardzo trudno nie poddać się takim pokusom jak mała drzemka, obejrzenie czegoś w TV, zajęcie się czymkolwiek tylko nie pracą. Trzeba mieć naprawdę silny charakter.
  • Tracisz większość a nawet wszystkie przywileje jakie przysługują innym w Twojej firmie np. bezpłatna stołówka, bezpłatne napoje czy niepubliczna opieka zdrowotna.
  • W kryzysie będziesz zapewne pierwszy na liście do wywalenia. Łatwiej zwolnić Ciebie niż kolegę z którym się chodzi na piwo. Wskazówka: jak szef zaprasza Cię na piwo to jedź bez względu na wszystko :)

Inne wskazówki

  • Zapomnij o pracy w dowolnych godzinach. To w znacznej większości przypadków się nie sprawdza. Cały zespół musi pracować mniej więcej w tym samych godzinach. Jak Ci się marzy dowolność w tej kwestii to załóż firmę, zostań freelancerem. W pracy zdalnej nie pobyczysz się do południa. Wyjątkiem są tylko baaaardzo luźne zadania.
  • Uczestnicz we wszystkich inicjatywach jakie proponuje firma by integrować pracowników. To Twoja jedyna szansa żeby nawiązać z nimi normalne relacje. Jeżeli jest taka szansa, namów wszystkich na jakiś wyjazd integracyjny w Twoje strony, do Twojego miasta etc.
  • Fajnie jest posiedzieć w domu ale po jakimś czasie zaczniesz coraz bardziej tęsknić za pracą w biurze, będziesz szukał każdej możliwości aby wyrwać się poza cztery ściany. Musisz sobie jakoś zorganizować czas po pracy bo siedzenie przed TV i picie zimnego piwka nie będą już wcale takim miłym scenariuszem na wieczór.
  • Nawet jeżeli nie prowadzisz aktywnego trybu życia to pracując w biurze wykonujesz ten minimalny wysiłek fizyczny potrzebny do normalnego funkcjonowania Twojego organizmu. Jeżeli tego zabraknie a Ty będziesz się tylko przesiadał z fotela przed biurkiem na fotel przed TV to prędzej czy później podupadniesz na zdrowiu. Ostrzegam całkiem poważnie. Wystarczy chociażby codzienny półgodzinny spacer.

Z punktu widzenia pracodawcy

Zalety

  • Dobrze wypracowany system pracy zdalnej ułatwia rekrutację. Problemy ze znalezieniem pracowników będą zawsze ale od teraz będzie trochę łatwiej.
  • Teoretycznie możesz zatrudnić każdego.
  • Nie ponosisz kosztów nowego stanowiska pracy. A już na pewno nie w takim stopniu jak przy pracy stacjonarnej.
  • Pracownik jest raczej punktualny. Wymówka, że stał w korku nie przejdzie :)
  • Kobiety w ciąży i po porodzie mogą prawie cały czas pracować.

Wady

  • Komunikacja w zespole jest utrudniona. Nie przeskoczysz tego ale można osiągnąć dobry poziom.
  • Mogą się pojawić problemy czysto technologiczne takie jak dostęp pracownika zdalnego do firmowego serwera produkcyjnego itd.

Inne wskazówki

  • Zespoły pracowników zdalnych i stacjonarnych powinny mieć ze sobą stały kontakt ale każdy z takich zespołów powinien mieć własnego lidera do najważniejszych spraw. Oczywiście nie dotyczy to sytuacji gdy w którejś grupie jest tylko jeden pracownik :)
  • Bądź sprawiedliwy. Pracownik zdalny na wielu płaszczyznach współpracy ma trudniej.
  • Odległość pracownika od firmy nadal może być ważna. Jeżeli pracownik zdalny może dojechać do firmy maksymalnie w kilka godzin to chyba nie jest źle. Osobiście nigdy nie miałem potrzeby takiego pilnego spotkania ale może kogoś taka możliwość uspokaja ;)
  • Samodyscyplina, samodzielność i terminowość – bardzo ważne cechy, których powinieneś oczekiwać od pracowników zdalnych jeżeli nie chcesz mieć z nimi ciągle pod górkę.
  • Czasami jest trudniej kontrolować postępy pracy pracowników zdalnych a czasami nie. Zależy od trybu pracy, konkretnego zlecenia itd. Nie daj się jednak nabrać przekonaniu, że jak ktoś pracuje zdalnie to na pewno się obija i nie da się nad nim zapanować.

Każdy sam powinien wyliczyć sobie bilans zalet i wad ale mam nadzieję, że uświadomiłem przynajmniej niektórym, że praca zdalna to duże wyzwanie. Ja nie mam wielkiego wyboru, albo muszę pracować zdalnie albo przeprowadzić się do innego miasta. To w końcu nastąpi (przeprowadzka) ale póki co, dalej będę pracował zdalnie. Gdybym jednak miał łatwiejszy wybór, wybrałbym powrót do pracy w biurze (pracowałem tak ponad dwa lata nim zacząłem pracę zdalną).


Łatwiejsze zarządzanie serwerem Minecraft

09 maja 2011

Wygląda na to, że temat Minecraft’a zagości na tym blogu na dłużej bo zarządzanie Debianem i samym serwerem Craftbukkit sprawia mi wielką frajdę ;)

Szukając jakiegoś gotowca do robienia backupów map Minecrafta natrafiłem na arcyciekawy wpis kolegi ze Słowacji gdzie można znaleźć pakiet skryptów *.sh do podstawowej obsługi serwera Craftbukkit. Lekko je dostosowałem do własnych potrzeb (tak aby były kompatybilne z tym co opisałem we wcześniejszym wpisie).

Co dają nam te skrypty?

  • Zgrabne startowanie, restartowanie i zatrzymywanie serwera. Wszystko z powiadomieniami dla graczy.
  • Automatyczny backup naszych map.
  • Automatyczny restart serwera w wybranych godzinach (w przykładzie o 5:30 rano) aby oczyścić RAM serwera, pozwolić mu zaczerpnąć powietrza ;)
  • Automatyczne sprawdzanie co pół godziny czy serwer nadal działa. Gdy coś padnie a Ciebie nie będzie to jest duża szansa, że serwer sam wstanie.

Skrypty:

bukkit_start.sh – prosty skrypt startujący serwer. Od siebie dodałem obsługę pobierania nowych wersji serwera Craftbukkit. Raczej nie wywołuj go bezpośrednio, jest stworzony na potrzeby reszty skryptów.

#!/bin/sh

if [ $# -eq 1 ]
then

    if [ $1 = 'l' -o $1 = '-l' ]
    then

        echo "Pobieranie ostatniej wersji Bukkit"

        wget http://ci.bukkit.org/job/dev-CraftBukkit/lastBuild/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar
        mv -T craftbukkit.jar craftbukkit-last.jar
        mv -T craftbukkit-0.0.1-SNAPSHOT.jar craftbukkit.jar

    elif [ $1 = 'r' -o $1 = '-r' ]
    then

        echo "Pobieranie ostatniej rekomendowanej wersji Bukkit"

        wget http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar
        mv -T craftbukkit.jar craftbukkit-last.jar
        mv -T craftbukkit-0.0.1-SNAPSHOT.jar craftbukkit.jar

    fi

fi

java -d64 -Xincgc -Xmx1280M -jar craftbukkit.jar nogui

start.sh – nasz główny skrypt do startowania serwera. Sam martwi się o utworzenie screen’a dla Minecrafta (ale nie zakotwicza go do naszego okna). Nadal możesz używać parametrów -r i -l do pobierania nowych wersji Craftbukkit (opisane tutaj)

#!/bin/bash

if [ $# -eq 1 ]
then
    screen -S minecraft -t world -d -m /opt/craftbukkit/bukkit_start.sh $1
else
    screen -S minecraft -t world -d -m /opt/craftbukkit/bukkit_start.sh
fi

backup.sh – skrypt robi backup map serwera. Powiadamia grających użytkowników o przebiegu procesu, troszczy się o zapisanie mapy, kopiuje pliki i sam usuwa stare kopie bezpieczeństwa. Możesz skorzystać z wersji, która pakuje wszystko do plików zip ale ja stosuję proste kopiowanie wszystkich plików i folderów (działa szybciej a miejsca na dysku i tak nie brakuje). Ten skrypt kopiuje mapy o nazwach normal, nether i survival. Będziesz pewnie musiał dostosować skrypt do własnych potrzeb.

Jest też jedna wada. Skrypt robi backup nawet gdy między jedną kopią bezpieczeństwa a drugą nie było żadnych graczy. W takiej sytuacji nie ma powodu do robienia kopii bo nic się nie zmieniło na mapach. Można to załatwić poprzez użycie pluginu Backup. Przez jakiś czas go używałem i sprawuje się znakomicie. Zrezygnowałem z niego tylko dlatego, że wolę mieć pełnię władzy nad wszystkimi procesami związanymi z serwerem Minecrafta a dodatkowe, niepotrzebne kopie nie są dla mnie problemem (i tak się same usuną po dwóch dniach).

#!/bin/bash
# Minecraft AutoBackup

cd /opt/craftbukkit/

if [ -e server.log.lck ] #check if server is running
then
    screen -S minecraft -p world -X stuff "say Generowanie kopii bezpieczenstwa"`echo -ne '\015'`
    screen -S minecraft -p world -X stuff "save-off"`echo -ne '\015'`
    screen -S minecraft -p world -X stuff "save-all"`echo -ne '\015'`

    #zip -v backups/normal-`date "+%Y-%m-%d-%H-%M-%S"`.zip -r normal
    #zip -v backups/nether-`date "+%Y-%m-%d-%H-%M-%S"`.zip -r nether
    #zip -v backups/survival-`date "+%Y-%m-%d-%H-%M-%S"`.zip -r survival

    cp -r normal backups/normal-`date "+%Y-%m-%d-%H-%M-%S"`
    cp -r nether backups/nether-`date "+%Y-%m-%d-%H-%M-%S"`
    cp -r survival backups/survival-`date "+%Y-%m-%d-%H-%M-%S"`

    screen -S minecraft -p world -X stuff "save-on"`echo -ne '\015'`
    screen -S minecraft -p world -X stuff "say Kopia wygenerowana"`echo -ne '\015'`

    #dla plikow zip
    #find /opt/craftbukkit/backups/ -type f -mmin +2880 -exec rm {} \;

    find /opt/craftbukkit/backups/ -type d -mmin +2880 -exec rm -r {} \;
fi

restart.sh – restartuje serwer i ładnie powiadamia użytkowników o całym procesie.

#!/bin/bash
# Minecraft AutoRestart

cd /opt/craftbukkit/

screen -S minecraft -p world -X stuff "say Automatyczny restart za minute"`echo -ne '\015'`

sleep 50

screen -S minecraft -p world -X stuff "say Automatyczny restart za dziesiec sekund!"`echo -ne '\015'`

sleep 5

screen -S minecraft -p world -X stuff "say Automatyczny restart za piec sekund!"`echo -ne '\015'`
screen -S minecraft -p world -X stuff "save-all"`echo -ne '\015'`

sleep 5

screen -S minecraft -p world -X stuff "stop"`echo -ne '\015'`

sleep 10

screen -S minecraft -t world -d -m /opt/craftbukkit/bukkit_start.sh

sleep 20

screen -S minecraft -X stuff "say I po restarcie..."`echo -ne '\015'`

check.sh – sprawdza czy serwer działa. Jeżeli nie to go startuje i zapisuje logi z wydarzenia.

#!/bin/sh

cd /opt/craftbukkit/

if [ -e server.log.lck ]
then

    echo "Serwer dziala!"

else

    echo "Server nie dziala!"

    screen -S minecraft -t world -d -m /opt/craftbukkit/bukkit_start.sh

    NOW=$(date +"%b-%d-%y %H:%M")
    echo '[' $NOW ']: Serwer nie dzialal... Ale juz dziala!' >> /opt/craftbukkit/ServerCheck.log

fi

stop.sh – mój prosty skrypt do zatrzymania serwera, bez restartu.

#!/bin/sh

cd /opt/craftbukkit/

if [ -e server.log.lck ]
then

    screen -S minecraft -p world -X stuff "say Zatrzymanie serwera za 10 sekund"`echo -ne '\015'`

    sleep 10

    screen -S minecraft -p world -X stuff "stop"`echo -ne '\015'`

else

    echo "Server nie dziala!"

fi

Na koniec podaję wpisy jakie powinny znaleźć się w Cronie aby móc w pełni korzystać z dobrodziejstw wyżej wypisanych skryptów:

## Minecraft
#Backup map co godzine
0  *  *  *  *   cd /opt/craftbukkit && ./backup.sh > /dev/null 2>&1
#Restart serwera o godzinie 5:30
30  5  *  *  *  cd /opt/craftbukkit && ./restart.sh > /dev/null 2>&1
#Sprawdzamy co pol godziny czy serwer dziala, jezeli nie to go podnosimy
*/30  *  *  *  * cd /opt/craftbukkit && ./check.sh > /dev/null 2>&1

Pamiętajcie o uprawnieniach dla skryptów! Komenda chmod +x NAZWA_PLIKU.


Instalacja serwera Minecraft

28 kwietnia 2011

Gry Minecraft nie muszę chyba nikomu przedstawiać. A jeżeli ktoś jej naprawdę nie zna to w sieci jest o niej zatrzęsienie materiałów i nie ma sensu ich tutaj powielać. Jakiś czas temu postanowiłem połączyć przyjemne z pożytecznym i w ramach podnoszenia swoich umiejętności obsługi systemów Linux postawiłem serwer Minecraft na serwerze VPS z systemem Debian.

Minecraft ma swoje własne oficjalne oprogramowanie do serwerów multiplayer ale serwery budowane przez społeczność* są lepsze, bardziej rozbudowane, dają większe możliwości konfiguracji i rozszerzania itd. Zgaduję, że w tej chwili najpopularniejszy jest Bukkit**. Właśnie jego wybrałem i na nim się teraz skupimy.

Tak naprawdę instalacja jest banalna ale zauważyłem, że wiele osób szuka informacji i chyba przyda się taka mała ściągawka. Dodam w tym miejscu tylko tyle, że nie chcę się tutaj przesadnie skupiać na obsłudze samego Debiana. Musisz sobie z tym poradzić sam ale wskazówek w sieci jest pod dostatkiem.

Niektóre elementy poniższej listy zostały napisane pod osoby, które swój serwer VPS/dedykowany zakupiły trzy minuty temu. Jeżeli administrujesz serwerem już jakiś czas to nie wszystko musisz robić ale pewnie sam zdajesz sobie z tego sprawę ;)

Robiłem wszystko z poziomu root’a.

Jedziemy:

  • Przeczytaj to http://wiki.bukkit.org/Setting_up_a_server. Zrobimy trochę inaczej ale przeczytanie oficjalnych zaleceń nikomu nie zaszkodzi :)
  • Połącz się z serwerem. Nie wiesz jak? Skorzystaj z PuTTY i tym tropem podążaj w google :) Przy okazji dodam, że najprawdopodobniej możesz się także połączyć ze swoim serwerem za pomocą klienta SFTP. Ja polecam WinSCP. Jeżeli trudno Ci się poruszać po serwerze za pomocą konsoli to klient SFTP będzie dla Ciebie bardzo pomocny.
  • Przejdź do pliku /etc/apt/sources.list. Znajdują się tu adresy skąd Twój system powinien pobierać paczki oprogramowania. Ja mam tam wpisane następujące adresy:

    Debian 5

    deb http://ftp.de.debian.org/debian/ lenny main non-free contrib
    deb-src http://ftp.de.debian.org/debian/ lenny main non-free contrib
    deb http://security.debian.org/ lenny/updates main contrib non-free
    deb-src http://security.debian.org/ lenny/updates main contrib non-free
    
    deb http://www.backports.org/debian etch-backports main contrib non-free
    

    Debian 6

    deb http://ftp.pl.debian.org/debian/ squeeze main non-free contrib
    deb-src http://ftp.pl.debian.org/debian/ squeeze main non-free contrib
    deb http://security.debian.org/ squeeze/updates main contrib non-free
    deb-src http://security.debian.org/ squeeze/updates main contrib non-free
    deb http://ftp.pl.debian.org/debian/ squeeze-updates main non-free contrib
    deb-src http://ftp.pl.debian.org/debian/ squeeze-updates main non-free contrib
    
    deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
  • Dokonaj aktualizacji wszystkich paczek. Zrobisz to za pomocą następującej komendy:
    apt-get update
  • Sprawdź czy masz zainstalowaną Jave (polecenie java -version powinno zwrócić jakieś informacje o Javie). Wyczytałem, że Bukkit nie zadziała z Javą w wersji OpenJDK (kiedyś chyba działał). Jeżeli nie masz Javy to uruchom następujący kod:
    apt-get install sun-java6-jre

    Teraz wypadałoby napisać czym różni się Java w wersji JRE od JDK. Ten cytat z Wikipedii wyjaśnia wszystko:

    JRE (Java Runtime Environment) – udostępnia kod bajtowy wszystkich klas standardowych i wirtualną maszynę do ich uruchamiania, zaś JDK (Java Development Kit) dodatkowo udostępnia źródła tych klas oraz dodatkowe narzędzia takie jak kompilator, paker czy debuger. Podział ten wprowadzono dlatego, że użytkownik Javy do uruchamiania programów potrzebuje tylko JRE, natomiast do programowania działających aplikacji potrzeba już JDK.

    Administrując serwerem Minecraft nigdy nie miałem potrzeby czegokolwiek kompilować więc moim oczywistym wyborem jest JRE. Jeżeli jednak z jakiegoś powodu chcesz mieć JDK to pakiet ten instaluje się identycznie, wystarczy zmienić literki na końcu polecenia.

    Wskazówka: podczas instalacji Javy pojawią się dwa „okienka” z informacjami o licencji. Aby w pierwszym „kliknąć” na Ok a w drugim zgodzić się na warunki licencji używaj klawisza Tab.

  • W /opt/ stwórz katalog o nazwie craftbukkit.
  • Do /opt/craftbukkit/ wgraj plik o nazwie start.sh o następującej zawartości:
    #!/bin/sh
    
    if [ $# -eq 1 ]
    then
    
        if [ $1 = 'l' -o $1 = '-l' ]
        then
    
            echo "Pobieranie ostatniej wersji Bukkit"
    
            wget http://ci.bukkit.org/job/dev-CraftBukkit/lastBuild/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar
            mv -T craftbukkit.jar craftbukkit-last.jar
            mv -T craftbukkit-0.0.1-SNAPSHOT.jar craftbukkit.jar
    
        elif [ $1 = 'r' -o $1 = '-r' ]
        then
    
            echo "Pobieranie ostatniej rekomendowanej wersji Bukkit"
    
            wget http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar
            mv -T craftbukkit.jar craftbukkit-last.jar
            mv -T craftbukkit-0.0.1-SNAPSHOT.jar craftbukkit.jar
    
        fi
    
    fi
    
    java -d32 -Xincgc -Xmx768M -jar craftbukkit.jar nogui
    

    W ostatniej linijce masz taki ciąg znaków: -d32. Jeżeli Twój system jest 32-bitowy to zostawiasz tak jak jest. Jeżeli system jest 64-bitowy to zamieniasz na -d64. W tej samej linijce masz ciąg znaków: 768M. Musisz tu wpisać ile RAM’u Twojego serwera chcesz przeznaczyć na Minecrafta. Niestety gra jest napisana w Javie i zżera ogromne zasoby :/ Wydajność to wielki problem tej gry.

  • Uruchom poniższą komendę aby umożliwić uruchamianie stworzonego przed chwilą pliku:
    chmod +x start.sh
  • Uruchom nasz skrypt z wymuszeniem ściągnięcia serwera (./start.sh -r o ile jesteśmy w katalogu /opt/craftbukkit/)
  • Olej wszystkie błędy :) Serwer na razie tworzy pliki konfiguracyjne etc.
  • Gdy serwer się uruchomił napisz stop i naciśnij Enter.
  • Teraz czeka nas konfiguracja serwera. Opiszę ją bardzo krótko, każdy powinien się bardziej w to zagłębić bo każdy ma inne potrzeby.
    • Najpierw plik ops.txt. Wpisujemy tu linijka pod linijką kolejne nicki operatorów serwera. Wpisuj wszystko małymi literami.
    • Następnie przechodzimy do pliku server.propeties. Tu jest kilka ustawień:
      level-name – nazwa Twojego świata. Może pozostać domyślna wartość.
      hellworld – decydujesz czy ma być dostępne tzw. piekło w Minecraft. Proponuję ustawić na false a dodatkowe światy obsługiwać za pomocą odpowiedniego pluginu np. MultiVerse.
      spawn-monsters – mają się pojawiać potwory?
      online-mode – podczas logowania użytkownika serwer ma sprawdzać czy posiada on oryginalną wersję gry?
      spawn-animals – mają się pojawiać zwierzęta?
      max-players – maksymalna ilość graczy jednocześnie
      server-ip – zostaw puste
      pvp – czy gracze mogą ze sobą walczyć i zadawać sobie rany?
      level-seed – seed mapy***. Można pozostawić puste, wtedy seed wylosuje się sam.
      server-port – port pod jakim ma być dostępny serwer. Można zostawić domyślną wartość.
      allow-flight – czy dozwolone jest latanie?
      white-list – wpuszczać tylko tych użytkowników, którzy są na białej liście?
      spawn-protection – nie jestem pewien do końca za co odpowiada to ustawienie. Nie chce mi się szukać ;) Domyślam się, że określa ilość kratek od punktu startu gry (tzw. spawn) w obrębie których to klatek nie działa np. PVP, bez względu na ustawienia serwera.
    • Plik white-list.txt wypełniamy tylko gdy w server.propeties ustawiliśmy opcję white-list na true. W pliku tym wpisujemy nicki osób, jeden pod drugim. Tylko osoby z tej listy będą wpuszczane na serwer.
  • Na tym konfiguracja serwera się kończy. Możemy ponownie go uruchomić (./start.sh). Nie powinno być już żadnych błędów. Wszystko co „wypluwa” serwer do konsoli możesz przeglądać w pliku server.log.

Serwer działa ale przestanie działać gdy tylko wyłączysz PuTTY. Jak temu zaradzić? Najprościej za pomocą pakietu screen. Najpierw instalacja (wcześniej wyłącz serwer Minecrafta poprzez polecenie stop):
apt-get install screen

Następnie w katalogu /opt/craftbukkit/ wpisujemy to:
screen -dR minecraft

Teraz uruchamiamy serwer:
./start.sh

Działa tak jak zawsze z tym, że teraz spokojnie możemy zamknąć PuTTY a serwer dalej działa. Jeżeli po wyłączeniu konsoli zapragniemy wrócić do naszego serwera to po zalogowaniu na swoje konto serwerowe wystarczy wpisać ponownie screen -dR minecraft i włączy nam się w konsoli nasz serwer. Aby z niego wyjść (oczywiście bez jego wyłączania) naciśnij kombinację przycisków Ctrl+a, puść je i naciśnij literkę d. W ten sposób wrócisz do konsoli ale serwer dalej będzie działał.

Bukkit jest aktualizowany praktycznie codziennie, czasami kilka razy na dzień. Część aktualizacji jest ustawiana jako rekomendowane, część to tylko drobne lub niepełne zmiany. Wszystkie buildy znajdziesz na stronie www.ci.bukkit.org/job/dev-CraftBukkit/. Swój serwer możesz łatwo zaktualizować dzięki tym komendom (najpierw oczywiście zatrzymaj serwer):
./start.sh -r
Zaktualizuje serwer do najnowszej rekomendowanej paczki
./start.sh -l
Zaktualizuje serwer do najnowszej paczki, niekoniecznie rekomendowanej

Po każdej aktualizacji automatycznie uruchamiany jest serwer. Jeżeli po aktualizacji coś jest nie tak (serwer się nie uruchamia, są jakieś błędy etc.) to Twoja ostatnia wersja serwera jest pod nazwą craftbukkit-last.jar.

Gratuluję, Twój serwer powinien już działać. Możesz się na niego zalogować jako gracz podając w kliencie Minecraft adres IP swojego serwera oraz port w postaci IP:port. Jeżeli port zostawiłeś domyślny (25565) to możesz go pominąć i podać tylko IP. Oczywiście można również ustawić to w taki sposób aby nie wpisywać IP a jakąś domenę ale to już sprawa na inny wpis… :)

Prawdziwą siłą Bukkita jest duża baza pluginów, które ułatwiają pracę administratorom/moderatorom, dodają nowe funkcjonalności itd. Namawiam do regularnego sprawdzania bazy pluginów.

Ciekawe artykuły o instalacji/uruchomieniu/obsłudze serwera Bukkit: [1], [2], [3]. Czytaj je jednak z głową bo nie wszystko tam jest prawidłowe… Na przykład zachęta do instalacji OpenJDK lub gorszy sposób uruchomienia serwera (komenda java -Xmx2048M -Xms2048M -jar minecraft_server.jar, która jest odradzana na oficjalnym forum Bukkita).

EDIT 09-05-2011
Gorąco namawiam do przeczytania mojego drugiego wpisu na temat serwera Minecraft. Znajdziesz tam kilka bardzo pomocnych skryptów do zarządzania Craftbukkit.

Przypisy
* – Nigdy nie sprawdzałem jak to wygląda od strony technicznej ale wyczytałem, że CraftBukkit to nakładka na oficjalny serwer, która udostępnia nowe możliwości/ulepszoną komunikację z oficjalnym serwerem. A więc nie jestem pewien czy można tu mówić o samodzielnym serwerze. Dla mnie to nie ma znaczenia ale wyjaśniam żeby ktoś mnie nie posądził, że podaję błędne informacje ;)

** – Tak naprawdę to serwer nazywa się CraftBukkit a Bukkit to API dla deweloperów dzięki któremu łatwiej im się komunikować w ich pluginach z serwerem Minecrafta. Dla uproszczenia będę nazywał serwer jako Bukkit. Sami twórcy tak postępują :)

*** – Każda mapa w Minecraft ma tzw. seed czyli ciąg znaków na podstawie którego generator terenu generuje kolejne porcje mapy. Dla graczy oznacza to ważną informację: jeżeli sami podamy seed to ilekroć będzie on taki sam tyle razy wygeneruje nam się identyczna mapa.


DiscoverPHP.com – mój projekt Open Source napisany w Zend Framework

14 marca 2011

Ostatnio, o czym już wspominałem, namiętnie studiuję możliwości Zend Framework. Najlepsza nauka to praktyka. Postanowiłem więc stworzyć jakąś małą stronkę na której przećwiczę działanie najpopularniejszych elementów ZF.

Zend Framework ma dość wysoki próg startu. Na początku pracy z nim, przeraża możliwościami, uniwersalnością, mnogością rozwiązań każdego problemu. Programista rzucany jest na głęboką wodę. Oczywiście każdy uparty wyjdzie z tego o własnych siłach ale to nie zmienia faktu, że jest trudno.

Dla mnie osobiście największą zaletą ZF jest to, że daje ogromną swobodę programiście. Paradoksalnie, na początku była to dla mnie również największa przeszkoda. Nie zastanawiałem się tyle nad tym jak coś oprogramować w PHP (dokumentacja jest taka sobie ale można też analizować kod, który tylko na początku wydaje się taki straszny) co nad wyborem najlepszego, najmądrzejszego rozwiązania. „Czy ten plik powinien być tutaj czy tam? Jak zorganizować strukturę aplikacji? Który sposób jest najlepszy aby dostać się do tej metody?”. Niefrasobliwy programista nie zadawałby sobie takich pytań, zrobiłby tak jaka byłaby jego pierwsza myśl i pewnie zadziałałoby. Nie po to jednak sięgamy po Zend Framework żeby tworzyć niechlujny, nielogiczny kod, łamiący zasady np. wzorców architektonicznych.

W sieci jest trochę przykładów użycia ZF ale napotykamy na wiele przeszkód. Albo są to przykłady stare (i teraz robi się daną rzecz zupełnie inaczej) albo bardzo malutkie, nie traktujące problemu całościowo lub wręcz przeciwnie, ogromne kobyły do których nie wiadomo jak się dotknąć.

Aby chociaż trochę odciążyć nowych odważnych wkraczających w świat ZF, postanowiłem na samym początku, że moja strona będzie publicznie dostępna, razem z kodem źródłowym. Tak powstała witryna discoverphp.com.

Strona sama w sobie nie jest drugim facebookiem :D Mimo to udało mi się napisać tam trochę fajnego kodu, użyć kilka najpopularniejszych modułów ZF, zastosować kilka sztuczek. Starsi wyjadacze nie znajdą dla siebie tam nic ciekawego (chyba, że z jakimś modułem nie mieli do tej pory w ogóle do czynienia) ale dla świeżaków może to być bardzo pomocne i inspirujące.

Proszę jedynie wszystkich o wyrozumiałość bo sam zabawę z ZF dopiero zacząłem i mam jeszcze wiele pytań. Targają mną wątpliwości co do niektórych rozwiązań w kwestii organizacji kodu, architektury aplikacji (moje modele wydają mi się paskudne :/). Pewnie nie prędko się ich wyzbędę, jestem otwarty na podpowiedzi i konstruktywną krytykę ;)

Cały czas chcę mieć styczność z Zend Frameworkiem i mam plan rozwijać stronę DiscoverPHP.com, dodając nowe możliwości (a przede wszystkim nowy kod w ZF, używać nowych modułów). O poważniejszych zmianach będę informował na blogu.

Na koniec dwa linki:
www.discoverphp.com/pl/geneza – krótko o projekcie plus lista rzeczy, których można się nauczyć z kodu
www.discoverphp.com/pl/zrodlo – kod źródłowy do pobrania


Znowu lubimy target=”_blank”

10 marca 2011

Przez ostatni rok wiele się mówiło o HTML5 w kontekście tagów audio i video, nowych tagów takich jak header, article, footer itp. oraz walki z Flashem. Tymczasem niezauważona przemknęła informacja, że atrybut target="_blank" wraca do łask!

Konsorcjum W3C dawno temu postanowiło, że atrybut umożliwiający otwieranie linków w nowym oknie ma być zdeprecjonowany (deprecated) co przeważnie oznacza jego całkowite usunięcie w przyszłych wersjach języka. Główny argument był taki, że to użytkownik ma mieć możliwość decydowania w jaki sposób będzie otwierał linki. Jeżeli zechce otworzyć link w nowym oknie to naciśnie środkowy przycisk myszki lub skorzysta z menu kontekstowego.

Założenia szlachetne ale niestety teoria nie wytrzymała zderzenia z praktyką. Przede wszystkim, większość użytkowników sieci nie jest świadoma konsekwencji jakie niesie za sobą otwieranie linków w tym samym lub w nowym oknie. Większość klika lewym przyciskiem myszy a potem "spaceruje" po stronach korzystając z przycisków poprzednia/następna, skutecznie się gubiąc po chwili. Po drugie, ciężko jest właścicielom stron przełknąć gorzki fakt, że niestosowanie target="_blank" powoduje ucieczkę użytkowników z ich stron. W ekstremalnym scenariuszu mogłoby to spowodować ograniczenie linkowania w sieci a przecież linki to podstawa Internetu! Po trzecie wreszcie, nietrudno podać przykłady gdzie otwieranie nowego okna jest mocno zalecane np. gdy ktoś wypełnia długi formularz i na końcu ma link do regulaminu, który należy zaakceptować. Nieuważny użytkownik kliknie go lewym przyciskiem myszy i straci wszystko co wpisał w formularzu.

Wyżej wymienione powody doprowadziły do tego, że webmasterzy albo używali dalej target="_blank" i olewali standardy (a nie ma się co martwić, że przeglądarki kiedykolwiek przestaną obsługiwać ten atrybut z wartością _blank) albo oszukiwali walidatory różnymi rozwiązaniami w JavaScript albo zaciskali zęby i linkowali zgodnie z zaleceniami W3C (ale przeważnie robili to ze łzami w oczach :) ).

W3C wreszcie dostrzegło, że ich zakaz jest niemile widziany przez dużą część webmasterów. Dalsze upieranie się przy swoim nie miało sensu i zniesiono zapis "deprecated" dla target="_blank". Linki potwierdzające ten fakt:
http://www.w3.org/TR/html5-diff/#changes-2008-01-22
http://www.w3.org/TR/html5/browsers.html#valid-browsing-context-name-or-keyword

I jeden cytat:

"the target attribute for the a and area elements is no longer deprecated, as it is useful in Web applications, e.g. in conjunction with iframe."

Osobiście byłem przeciwnikiem zakazywania target="_blank" czego mogliście doświadczyć na tym blogu :) Jednocześnie dostrzegam logikę w argumentach przeciwników decydowania za użytkownika. Problem co prawda stracił na ważności od czasu gdy pojawiły się w przeglądarkach karty (wcześniej otwierały się nowe okna co faktycznie było kłopotliwe) ale nadal istnieje. Dlatego proponuję wszystkim webmasterom oznaczanie wszystkich linków z target="_blank" odpowiednim symbolem. Efekt taki można uzyskać w bardzo prosty sposób:

CSS:
  1. a[target="_blank"] {
  2.   padding-right: 18px;
  3.   display: inline-block;
  4.   line-height: 14px;
  5.   background: url(new_window.png) center right no-repeat;
  6. }

Efekt prezentuje się tak: otworzy się w nowym oknie. Wartości przy padding-right i line-height ustaw według własnego uznania, pamiętając o wymiarach ikonki nowego okna.


Standardy tworzenia kodu w PHP

02 marca 2011

Jak już nie raz pisałem, PHP jest krytykowane za to, że daje zbyt dużą swobodę programiście podczas tworzenia kodu. Jest w tym trochę prawdy aczkolwiek to długi i skomplikowany temat. Nie mam ambicji aby proponować tu rozwiązania w samym języku. Chcę poruszyć bardziej trywialny ale mimo to ważny problem jakim jest brak oficjalnych zaleceń co do formatowania kodu, nazewnictwa funkcji, klas etc. Społeczność PHP przez tyle lat nie dorobiła się spójnych standardów, które byłyby przestrzegane i promowane chociażby przez wszystkich liczących się graczy.

Całkiem nieźle pamiętam czasy gdy większość programistów praktycznie wcale nie formatowała swojego kodu. Szczególnie olewano wcięcia. Nie było też żadnych zaleceń co do struktury katalogów i plików, nazewnictwa klas, funkcji, metod. Samowolka.

Prowadziło to do odruchów wymiotnych gdy los skazywał nas na pracę z kodem takiego niechlujnego programisty. Z czasem pojawiały się pierwsze propozycje takie jak wstawianie tu i ówdzie spacji dla większej czytelności kodu czy zasada "jedna klasa = jeden plik". Oczywiście to tylko przykłady, było tego więcej ale nawet dobrzy programiści stosowali te zasady wybiórczo. Frameworki przyniosły kolejną poprawę, przynajmniej w obrębie pojedynczych społeczności zrzeszonych wokół danego projektu.

Ten artykuł nie jest po to aby opisywać historię lub tworzyć/proponować nowe standardy. Jest po to aby zachęcić Cię do wybrania jednego, spójnego standardu i stosowania go. Jeżeli podchodzisz ambitnie do tego co robisz to nie masz innego wyjścia - musisz zostać programistycznym pedantem :)

Na pierwszy ogień idzie automatyczne ładowanie klas. Przez długie lata programista musiał sam dbać o to aby kod klasy był dostępny gdy chcemy utworzyć nowy obiekt. Ładował więc wszystkie klasy nawet gdy tylko część była używana lub przy każdym stworzeniu obiektu dołączał kod za pomocą include_once/require_once. Metody mało wydajne i kłopotliwe dla programisty. W PHP 5.1.2 nastąpił przełom, pojawiły się funkcje spl_autoload*. Jeżeli pierwszy raz o nich słyszysz to zapraszam do dokumentacji i google. W tym artykule istotniejsze od działania tego mechanizmu jest to, że społeczność PHP chyba po raz pierwszy postanowiła wspólnie wypracować jakiś standard. Owocem tych prac jest PSR-0. Standard ten odpowiada na wszystkie ważne pytania dotyczące automatycznego ładowania klas np. jak tłumaczyć nazwę klasy na ścieżkę do pliku czy gdzie w tym wszystkim jest miejsce na przestrzenie nazw wprowadzone w PHP 5.3. Standard ten zgodziły się promować takie marki jak Zend Framework czy Symfony (zresztą sami uczestniczyli w tworzeniu tego standardu) i powstało oczekiwanie w świecie PHP, że każdy poważny programista będzie się stosował do tych wskazówek. To daje wspaniałe możliwości, programiści rozumieją się bez słów a różne projekty można ze sobą w prosty sposób integrować.

Niestety w sprawie konkretnych rozwiązań programistycznych lista półoficjalnych (bo PSR-0 oficjalne chyba nie jest aczkolwiek ma błogosławieństwo od Zend) się kończy. Oczywiście istnieją powszechnie znane wskazówki ale dotyczą one raczej bardzo konkretnych fragmentów kodu i najczęściej są omawiane w pierwszych rozdziałach kursów PHP dla początkujących. Na końcu należy wspomnieć o pozytywnej modzie na używanie wzorców projektowych ale to bardzo obszerny temat i mogę w tej chwili napisać tylko tyle, że dobrze, że są :) I warto je stosować. Trzeba je stosować!

Osobna sprawa to formatowanie kodu. Przyznam, że temat bardzo mnie męczy bo co kod, co programista to trochę inne zasady (albo co gorsza, brak zasad). Ratunkiem są tu wcześniej wspomniane frameworki, które z dnia na dzień coraz bardziej lubię (o czym chciałbym wkrótce napisać). Zawierają one w swoich dokumentacjach standardy kodowania, które często są gotową ściągawką jak programować aby czytanie kodu było przyjemniejsze.

Jako świeżo upieczony programista Zend Framework stosuję się do stylu przez nich polecanego. Dokument jest tutaj a polska wersja tutaj. Wcześniej stosowałem się do standardów Drupala. Polecam również standardy Kohany i Symfony.

W dużej części są one ze sobą zbieżne, czasami różnią się szczegółami (Wcięcia na dwie czy cztery spacje? Ja wolę dwie ale ZF nakazuje cztery, jakoś przeboleję :) ). Nie jest tak bardzo istotne który standard wybierzesz (przeczytaj wszystkie), bylebyś wybrał jakikolwiek. Chodzi bardziej o ucywilizowanie programisty :) Gdy się przekona, że przestrzeganie tych zasad jest warte zachodu to zmiana drobnych szczegółów aby go "dopasować" do nowego projektu, nowego zespołu programistów będzie już łatwiejsza.

Stosujcie standardy!

EDIT
Polecam wpis Zyxa Propozycja zasad dobrego projektowania. Tomek opracował dokument, który w jednym miejscu zbiera zasady dobrego programowania w PHP. Lektura obowiązkowa! Nie każę Ci się bezwzględnie stosować do jego rad ale to na pewno skłoni Cię do przemyśleń. Myślenie jest dobre! :)


Zend_Navigation i własny routing

22 lutego 2011

Zend_Navigation to całkiem przyjemny moduł Zend Framework, który ułatwia nam tworzenie takich elementów strony jak menu czy tzw. breadcrumbs. Zend_Navigation dzieli się tak naprawdę na dwie części: Zend_Navigation_Page_Mvc i Zend_Navigation_Page_Uri. Krótko je opiszę:

  • Zend_Navigation_Page_Mvc pozwala niejako zintegrować Zend_Navigation z innymi elementami strony. Podczas konfiguracji Zend_Navigation_Page_Mvc musimy podać przynajmniej jeden z wymienionych elementów: action, controller, module lub route. Trzy pierwsze są chyba jasne, czwarty to nazwa routera z jakiego chcielibyśmy skorzystać. Na podstawie tych informacji Zend_Navigation_Page_Mvc wybierze odpowiedni router i później w oparciu o niego zbuduje linki np. w naszym menu. Zend_Navigation_Page_Mvc jest zalecane ponieważ ładnie się integruje z MVC, zmiany w routingu automatycznie wpłyną na działanie naszych elementów nawigacji.
  • Zend_Navigation_Page_Uri pozwala na budowanie linków bez oglądania się na pozostałe elementy strony. Sami wpisujemy jak link ma wyglądać i ZF nijak w to nie integruje. Jest to wygodne gdy chcemy wstawić pusty link (np. na potrzeby JavaScript) lub zewnętrzny odnośnik. Nie polecam natomiast używać tego sposobu do linkowania wewnętrznego. Od tego jest Zend_Navigation_Page_Mvc.

O ile w Zend_Navigation_Page_Uri kwestia linków jest jasna (sami sobie ustalamy jak mają wyglądać) o tyle w Zend_Navigation_Page_Mvc linki są budowane za pomocą Zend_Controller_Action_Helper_Url. Klasa ta tworzy link na podstawie konfiguracji jaką przekazaliśmy do Zend_Navigation. Szuka odpowiedniego routera, czyta zawarte w nim wskazówki i generuje link.

Z domyślnym routerem nie ma problemów. O jego działaniu można poczytać tutaj. W skrócie, linki budowane są w następujący sposób: controller/action. Można też dołączyć na początku nazwę modułu: module/controller/action. Jest także sposób na przekazywanie dodatkowych parametrów: controller/action/var1/value1/var2/value2.

Jeżeli adresy oparte są o taki domyślny router to Zend_Controller_Action_Helper_Url nie ma problemów z generowaniem linków. Do Zend_Navigation przekazujemy standardową konfigurację (pisałem o niej wcześniej: action, controller, module lub route) i aplikacja ma wszystkie potrzebne informacje wymagane do budowy linka.

Co jednak gdy mamy niestandardowy routing? Oto przykład z mojego kodu:

PHP:
  1. $router->addRoute(
  2.     'functions',
  3.     new Zend_Controller_Router_Route(
  4.         ':function',
  5.         array(
  6.             'controller' => 'function',
  7.             'action'     => 'function',
  8.             'function'   => ''
  9.         ),
  10.         array(
  11.             'function' => '\w*'
  12.         )
  13.     )
  14. );

Router nazywa się functions, przekierowuje na kontroler FunctionController i akcję functionAction. Link składa się tylko z jednego elementu (adresy mają taką postać: www.example.com/function), który został nazwany :function, domyślnie ma pustą wartość i może składać się z małych i dużych liter, cyfr i znaku podkreślenia _.

Czy Zend_Controller_Action_Helper_Url poradzi sobie ze zbudowaniem linku? Nie. Ma on co prawda informacje jaki router ma zostać użyty, jaki kontroler i akcja ale skąd ma wiedzieć co ma podstawić pod :function?

Tu dochodzimy do sedna sprawy. W konfiguracji Zend_Navigation trzeba uwzględnić fakt, że nie wszystkie elementy linka są znane i należy te braki uzupełnić. Służy do tego dodatkowe ustawienie. Zmienna $params w postaci tablicy w której podajemy wszystkie brakujące fragmenty linka.

Najlepiej zobrazować to na przykładzie. Oto wycinek (zmodyfikowany na potrzeby tego wpisu) mojej konfiguracji, dla pojedynczego elementu menu:

PHP:
  1.     'label'  => 'Nazwa linku',
  2.     'route'  => 'functions',
  3.     'params' => array('function' => 'moj_adres')
  4. );

Label to tzw. anchor linka. Route to nazwa routera. W params przekazujemy brakujące ogniwo czyli podpowiadamy, że w routerze :function ma zostać zastąpione przez moj_adres. Ostatecznie Zend_Navigation wygeneruje menu w którym będziemy mieli link w takiej postaci: www.example.com/moj_adres.


Zend Framework: własne ustawienia w application.ini

21 lutego 2011

Niedawno (bardzo niedawno) zacząłem bawić się Zend Framework. Aż wstyd, że dopiero teraz się za niego zabieram ale dlaczego tak właśnie się stało to już dłuższa historia, innym razem :) Jako bardzo początkujący w ZF mam wiele typowych, banalnych problemów. Chciałbym co jakiś czas napisać parę słów o tym oprogramowaniu ale nie oczekujcie jakiejś wielce tajemnej wiedzy. Dopiero się uczę.

Główna konfiguracja ZF znajduje się w configs/application.ini. Nic nie stoi na przeszkodzie aby stworzyć własny plik z innymi danymi konfiguracyjnymi, dedykowanymi naszej aplikacji. Ale jeżeli tych opcji nie jest zbyt dużo to szkoda męczyć serwer dodatkowym czytaniem i parsowaniem pliku. Warto rozważyć dodanie ustawień do głównego pliku konfiguracyjnego (wspomniany application.ini).

Początkowo myślałem, że istnieje jakiś z góry narzucony format własnych wpisów w application.ini a wartości tam zapisane są automatycznie dostępne w całej aplikacji. Nic z tych rzeczy.

W związku z tym możesz użyć dowolnego nazewnictwa podczas zapisywania swojej konfiguracji. Łatwiej jest pracować na przykładach więc załóżmy, że nasza strona ma mieć możliwość odczytania Twojej skrzynki pocztowej a wszystkie dane potrzebne do "wejścia" na nią będą w application.ini. Może to wyglądać tak:
mail.user = "mariusz"
mail.pass = "123"
mail.pop3 = "pop3.example.com"
mail.smtp = "smtp.example.com"
mail.port = "110"

Gdyby były wątpliwości, jest to fragment naszej konfiguracji z application.ini.

Konfiguracja zapisana ale jak się do niej dostać w kontrolerach, modelach etc.? Jak to zwykle bywa w ZF, sposobów jest wiele. Dla uzupełnienia dodam, że poniższe metody dadzą dostęp do całej konfiguracji z pliku application.ini, nie tylko do naszych ustawień.

W kontrolerze do konfiguracji można się dostać w ten oto sposób (kod do umieszczenia np. w jakiejś akcji):

PHP:
  1. $bootstrap = $this->getInvokeArg('bootstrap');
  2. $options = $bootstrap->getOptions();

Metoda ładna i przyjemna. W $config mamy zwykłą tablicę PHP, do konfiguracji możemy dostać się tak:

PHP:
  1. echo $options['mail']['user'];

Niestety sposób ograniczony tylko do kontrolera. Poza kontrolerem możesz zrobić tak:

PHP:
  1. $bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
  2. $options = $bootstrap->getOptions();

Ponownie konfigurację dostajemy w postaci tablicy.

Aby ustawienia były obiektem, można użyć Zend_Config. Nic prostszego:

PHP:
  1. $config = new Zend_Config($options);

Oczywiście $options to wcześniej wyciągnięte przez nas ustawienia, w postaci tablicy.

Teraz już mamy ładny, obiektowy dostęp do naszych danych skrzynki pocztowej. Sposób użycia:

PHP:
  1. echo $config->mail->user;

Nadal jednak może Ci się nie podobać, że w różnych miejscach aplikacji musisz używać różnych sposobów na wydobycie tych ustawień. Z pomocą przychodzi Zend_Registry. Gdzieś w pliku Bootstrap.php umieść tą metodę:

PHP:
  1. protected function _initConfig()
  2. {
  3.     $config = new Zend_Config($this->getOptions(), TRUE);
  4.     Zend_Registry::set('config', $config);
  5.     return $config;
  6. }

W pierwszej linijce przekazujemy do Zend_Config całą konfigurację. W Bootstrap jest do niej bezpośredni dostęp dlatego wystarcza $this->getOptions. Drugi parametr ustawiony na TRUE zezwala na późniejsze ewentualne modyfikacje konfiguracji. Ustaw zależnie od potrzeb. Po takich operacjach mamy w zmiennej $config obiekt ze wszystkimi ustawieniami.
Druga linijka zapisuje obiekt do rejestru. Od tej chwili w całej aplikacji jest bardzo łatwy dostęp do tych danych. Wystarczy w jakimkolwiek miejscu użyć takiego kodu:

PHP:
  1. echo Zend_Registry::get('config')->mail->user;

Prawda, że wygodne? Rejestr w Zend Framework to alternatywa dla różnego rodzaju metod do globalnego dostępu do danych. Tak naprawdę to do wszystkich ustawień z application.ini można się dostać z poziomu tablicy $GLOBALS:

PHP:
  1. $mail = $GLOBALS['application']->getOption('mail');
  2. echo $mail['user'];[

Nie polecam jednak takiej drogi na skróty. Pomijam już brzydotę tego rozwiązania :) Ale w przyszłości możemy się nieźle przejechać gdy w ZF coś zmienią. Lepiej używać do takich operacji dedykowanych sposobów.


Phing

12 lutego 2011

Istnieje dowcip, że komputer to narzędzie dzięki któremu rozwiązujemy problemy, które bez niego by nie istniały. Coś w tym jest. Mimo to komputery w dużej części służą do robienia różnych rzeczy szybciej, dokładniej, jednym słowem lepiej. Co dziwne, sami programiści czasami o tym zapominają i robią mnóstwo rzeczy "na piechotę" zamiast wyręczyć się maszyną.

Im bardziej skomplikowany jest projekt nad którym pracujemy tym bardziej złożony jest proces od tworzenia po wdrożenie kodu. Wgrywanie plików na kolejne serwery (produkcyjny, testowy etc.), pilnowanie spójności bazy danych, zarządzanie repozytorium, generowanie dokumentacji, wersjonowanie itd. To wszystko zabiera naprawdę mnóstwo czasu.

Czy można to jakoś zautomatyzować?
Oczywiście, że można i są do tego narzędzia, chociażby make. Pojawiają się jednak przeszkody.
Po pierwsze, są problemy z przenośnością między różnymi systemami. Najczęściej dane rozwiązanie działa tylko na jednej rodzinie systemów.
Po drugie, narzędzia te nie są łatwe (dla windowsowca make to naprawdę orka). Oczywiście ich nauka to samo dobro, przyda nam się na przyszłość ale czasami są ważniejsze rzeczy do poznania a i czas nie jest tu bez znaczenia.
Po trzecie wreszcie, przydałoby się nam narzędzie pomyślane i zaprojektowane stricte pod PHP. Najlepiej napisane w samym PHP bo po co nam kolejne technologie...

Panaceum na nasze bolączki okazuje się Phing.

Nie jest on nowym projektem. Nie mogłem doszukać się konkretnej daty jego startu ale wszystkie znaki na niebie i ziemi wskazują, że zaczęło się już w 2002 roku. Mimo upływu tylu lat, w Polsce (trudno mi oceniać jak jest w innych krajach) projekt nie jest chyba zbyt popularny. Takie jest przynajmniej moje wrażenie bo google nie zwraca zbyt wielu sensownych wyników na zapytanie "Phing" dla naszego języka, nie widywałem również dyskusji na forach/grupach dyskusyjnych o tym narzędziu a już zupełnie nikt o nim nie wspomina w CV lub ogłoszeniach o pracę. Błąd.

Sam zainteresowałem się Phingiem jakiś czas temu, co oznacza, że było to kiedyś ale nie pamiętam dokładnie kiedy :) Niestety, tylko na niego zerknąłem, stwierdziłem, że mi to nie jest potrzebne i zapomniałem. Faktycznie, wtedy nie było mi potrzebne ale z perspektywy czasu wiem, że rok, półtora roku temu Phing mógłby znacznie ułatwić mi życie.

Phing'a bardzo ładnie opisał zyxist w artykule Phing - system budowania dla PHP (proponuję zacząć naukę Phinga właśnie od tego artykułu) więc nie będę powielał tych informacji. Dla zachęty pozwolę sobie jedynie zacytować listę możliwości:

  • kopiowanie plików, katalogów,
  • tworzenie archiwów GZIP, BZIP2, ZIP,
  • tworzenie archiwów PHAR,
  • tworzenie pakietów PEAR i PEAR2,
  • zarządzanie numerami wersji,
  • wysyłanie plików na serwer FTP,
  • wysyłanie żądań HTTP, autoryzacja HTTP,
  • wysyłanie e-maili,
  • generowanie raportów pokrycia kodu testami (PHPUnit),
  • wykonywanie testów jednostkowych (PHPUnit),
  • generowanie dokumentacji API (PHPDocumentor),
  • obsługa systemów kontroli wersji: CVS, SVN, Git,
  • instalacja baz danych,
  • obsługa SCP i SSH,
  • wsparcie dla różnych narzędzi takich, jak PHP_CodeSniffer.

Lista ta jest niepełna, a wraz z rozwojem projektu liczba dostępnych typów zadań jest coraz większa.

Dodam od siebie jedynie tyle, że gdyby jednak czegoś Wam na tej liście brakowało to Phing'a można w łatwy sposób rozbudowywać pisząc specjalne rozszerzenia. Odsyłam do dokumentacji. Właśnie, dokumentacja całego projektu jest przyjemna, wszystko ładnie opisane, nikt nie powinien mieć problemów ze zrozumieniem.

Gdyby ktoś chciał poznać inne narzędzia tego typu to polecam zacząć od komentarzy do wcześniej podlinkowanego artykułu z zyxist.com. Warto przejrzeć również linki zamieszczone na końcu tekstu Automatyczne publikowanie aplikacji PHP autorstwa Jakuba Zalasa.