Certyfikaty od W3Schools

20 grudnia 2011

Certyfikaty to dobra rzecz, potwierdzają Twoją wiedzę. Jestem skłonny zaryzykować twierdzenie, że dla każdego normalnego pracodawcy jeden konkretny certyfikat może być więcej wart niż studia, nawet w oczekiwanym kierunku.

Problemem natomiast jest wybranie, który certyfikat chcemy zdobyć. Strona w3schools.com osiągnęła mistrzostwo w pozycjonowaniu przez co pojawia się na czołowych pozycjach W Google dla wielu zapytań o HTML, CSS a nawet PHP i MySQL. Nazwa nie pozostawia złudzeń, że to wszystko musi mieć coś wspólnego z konsorcjum W3C.

W3Schools oferuje na swojej stronie możliwość zdania płatnych, certyfikowanych egzaminów. Jest w czym wybierać. Na tą chwilę (grudzień 2011) mamy testy z HTML, CSS, JavaScript, jQuery, XML, ASP i PHP. Każdy za 95 dolarów (kiedyś było taniej :) ).

Na pierwszy rzut oka, wygląda atrakcyjnie. Wczytajmy się jednak w szczegóły.

  • Po pierwsze, egzamin zdajemy online. Każdy rozgarnięty w tej chwili sobie myśli „Ej! To co z wiarygodnością?”. Wiarygodność ma zapewnić ktoś od Ciebie :) Ktoś kto w teorii ma nad Tobą stać i patrzeć czy rozwiązujesz test samodzielnie a potem podpisać się pod certyfikatem. Od Ciebie zależy czy to będzie Twój kumpel z podwórka czy np. Twój szef ze znanej i szanowanej firmy IT. Oczywiście Twój Anioł Stróż mógłby Ci wystawić zwykłą rekomendację i miałaby taką samą moc no ale wtedy W3Schools by nie zarobiło :)
  • Test to 70 pytań wielokrotnego wyboru lub pytań TAK/NIE, limit czasu to 70 minut. Ja mam alergię na takie testy ale zdaję sobie sprawę, że to najprostsza i najszybsza forma egzaminu i może być nawet skuteczna o ile pytania są sensowne. W tym przypadku jednak nie są. Pytania są banalne. Tzn. nie wiem jakie są bo oczywiście nie przystąpiłem do żadnego testu ale są testy przykładowe i ich poziom woła o pomstę do nieba.
  • Jeżeli nie zdasz (minimum 75% poprawnych odpowiedzi) lub chciałbyś poprawić swój wynik to masz jeszcze jedną próbę. Jak rozumiem, w cenie.
  • W3Schools nie ma żadnego związku z konsorcjum W3C. Żadnego!

To wszystko powoduje, że nikt o zdrowych zmysłach nie weźmie pod uwagę tych certyfikatów. Więcej! Może uznać Cię za cwaniaka, który przyszedł go oszukać lub głupka, który dał się na tą farsę nabrać.

Do w3schools.com jest wiele więcej zarzutów. Społeczność webmasterska wyłapała wiele nieścisłości i błędów we wskazówkach tam umieszczonych. W swej złości stworzyli stronę w3fools.com gdzie bezwzględnie wytykają wszystkie grzechy autorów kursów.

Przy okazji, jakie certyfikaty warto zrobić?

Ja znam jeden dobry, certyfikat od Zend. W świecie PHP (w tej chwili certyfikat jest z PHP w wersji 5.3) nie ma cenniejszego certyfikatu. Osoby mocno związane z Zend Framework mogą też pomyśleć o certyfikacie z tego frameworka. Być może inne firmy egzaminują również z innych frameworków, CMS’ów itd.

Na pewno warto zastanowić się nad certyfikatami z bezpieczeństwa lub z baz danych. Szczegółów jednak nie podam bo ich nie znam :) Szukajcie przede wszystkim takich egzaminów, które mają błogosławieństwo od firm autorów oprogramowania.

Zdecydowanie nie warto podpierać się jakimikolwiek kursami i egzaminami z HTML i CSS. Wystarczy zrobić swoje portfolio i niech jego źródło mówi za nas. Miałbym również duże wątpliwości czy warto inwestować w coś co potwierdzi naszą znajomość Flasha i AS3. Natomiast jeżeli ktoś pracuje bardzo dużo z JavaScript to pewnie jakiś certyfikat byłby bardzo mile widziany (ale już nie z jQuery, to za proste!). Tylko czy coś takiego istnieje?


Konwersja domen IDN w PHP

14 grudnia 2011

Domeny z narodowymi znakami są już dłuższy czas dostępne ale nie przyjęły się za bardzo, przynajmniej nie w Polsce. Nie usprawiedliwia to jednak programistów, którzy o nich zapominają. Może to nam wygenerować poważne problemy.

Kilka dni temu musiałem poprawić pewien mały skrypcik. Administrator może podać adres, który potem jest używany w przekierowaniu PHP. Zwykłe, banalne header():

PHP:
  1. header('Location: '. $address);

I nagle zaskoczenie. Ten kod w Firefox i Safari (z Chrome i Operą było wszystko OK, IE nie testowałem) nie działa gdy zmienna $address to adres domeny z polskimi znakami diakrytyzowanymi!

Oczywiście pierwsza (i słuszna) myśl to przekodowanie takiej domeny do pierwotnej postaci. Jak powszechnie wiadomo, za tymi ładnymi narodowymi literkami kryją się okropne, niezrozumiałe krzaczki. Domena gżegżółka.pl tak naprawdę wygląda tak: xn--gegka-2ta76cmoc.pl. Do konwersji służy algorytm o nazwie Punycode.

Jeżeli masz PHP w wersji co najmniej 5.3 to rozwiązanie jest banalne. Masz dostępne dwie funkcje służące do konwersji z UTF8 do ASCII i z ASCII do UTF8.

Poniżej PHP 5.3 musisz posiłkować się zewnętrznymi bibliotekami. Najpopularniejsza z nich ma swoją stronę domową tutaj natomiast tutaj jest źródło do ściągnięcia.

Konwersja z UTF8 do ASCII:

PHP:
  1. require_once 'idna_convert.class.php';
  2.  
  3. $idn = new idna_convert();
  4. echo $idn->encode('http://www.gżegżółka.pl');

Otrzymamy:
http://www.xn--gegka-2ta76cmoc.pl

Konwersja z ASCII do UTF8:

PHP:
  1. require_once 'idna_convert.class.php';
  2.  
  3. $idn = new idna_convert();
  4. echo $idn->decode('http://www.xn--gegka-2ta76cmoc.pl');

Otrzymamy:
http://www.gżegżółka.pl

Jeżeli spróbujemy poddać konwersji normalną domenę, nie IDN, to nic się nie stanie więc funkcje/metody są bezpieczne i można ich używać na wszystkich domenach, bez dodatkowego rozróżniania. Pamiętaj tylko aby mieć adres w UTF8.


Linuxpl.com, SSH i wersja PHP

06 grudnia 2011

Skuszony wieloma rekomendacjami i niskimi cenami, postanowiłem skorzystać z oferty hostingowej linuxpl.com. Podstawowym plusem jest także możliwość zmiany wersji PHP na 5.3. Ta wersja pojawiła się dwa i pół roku temu a do tej pory nie jest dostępna na większości hostingów :/

Na linuxpl.com dostajemy również dostęp do SSH, co bywa dla mnie czasami zbawienne. W ustawieniach zmieniłem wersję PHP na 5.3 i z poziomu SSH chciałbym uruchamiać skrypty także pod tą wersją. Niestety, bez względu na ustawienia w panelu, komenda "php skrypt.php" pod SSH zawsze chce korzystać z PHP w wersji domyślnej dla linuxpl.com czyli PHP 5.2. Dokonałem tego odkrycia podczas gorączkowych przygotowań do uruchomienia lastdeal.pl więc postanowiłem nie czekać na support i rozwikłać zagadkę sam.

Nie da się na linuxpl.com sprawić aby zwykłe "php skrypt.php" działało w wersji innej niż PHP 5.2. Można jednak podać ścieżkę do innej wersji PHP. Jest to kłopotliwe bo trzeba wpisać za każdym razem długie ścieżki ale przynajmniej w ogóle się da. Swoją drogą niektóre (większość?) skrypty mają "na sztywno" wpisane samo "php coś tam" i trzeba będzie niestety je zedytować przed uruchomieniem.

Nie przedłużając, oto gotowa recepta.

Po zalogowaniu na SSH musisz zejść "niżej" w strukturze katalogów, wyjść ze swojego konta. Najlepiej "cd /". Binarka PHP w wersji 5.3 znajduje się tutaj: "./usr/local/php5.3/bin/php". Zamiast wpisywać "php skrypt.php" musisz wpisywać "./usr/local/php5.3/bin/php ./home/twoje_konto/domains/twoja_domena/public_html/skrypt.php".

Próbowałem zrobić symboliczny link aby chociaż trochę skrócić ścieżki ale niestety, nie powiodło się. Tam gdzie mam uprawnienia do tworzenia linków, tam nie zadziała ta binarka PHP. Trzeba zejść niżej, wyjść z własnego konta. A tam znowu nie mam już uprawnień...

Gdy była chwila spokoju, napisałem zapytanie do supportu. Potwierdzili to co sam znalazłem, dodając jedną wskazówkę:

jezeli chce pan uzyc swojego php.ini to komenda

/usr/local/php5.3/bin/php -c /usr/local/directadmin/data/users/lastdeal/php/lastdeal.pl/php.ini skrypt.php

Mam nadzieję, że ten wpis zaoszczędzi komuś trochę czasu i nerwów :)


Przyjazne adresy URL a wydajność

11 listopada 2011

Jakiś czas temu (kilka lat temu?) ktoś w komentarzu poprosił mnie o wytłumaczenie jak zniwelować dodatkowe obciążenie jakie generuje użycie przyjaznych adresów URL. Zacząłem o tym pisać a potem, z jakiegoś powodu, przerwałem i do tej pory nie znalazło się trochę czasu aby skończyć... Wiele artykułów mi w ten sposób przepadło. Tym razem dokończę dzieła :) A raczej napiszę od nowa bo wcześniej niepotrzebnie się rozpisałem...

Główne założenia: musisz napisać wydajną aplikację z przyjaznymi adresami URL w których nie przekazujesz żadnych identyfikatorów.

Przyjazne adresy to dzisiaj już konieczność. Ale wymagania wciąż rosną i teraz adresy muszą być jeszcze bardziej przyjazne niż kiedyś :) Nie tak dawno każdemu wystarczały adresy w postaci example.com/artykuly/1,jakis-adres/ czyli z przekazanym identyfikatorem zasobu. Te jednak okazały się zbyt brzydkie. Dzisiaj już nie chcemy identyfikatorów, chcemy czystych adresów czyli example.com/artykuly/jakis-adres/.

Oczywiście z punktu widzenia trudności zakodowania takiego rozwiązania, różnica jest niewielka. Jedno małe zapytanie do bazy danych gdzie wyszukamy identyfikator/dane artykułu na podstawie jego adresu. Czas wykonania się kodu też jakoś specjalnie się nie wydłuży. W czasach rozbudowanych frameworków z ich prostymi w użyciu routerami mało kto w ogóle sobie takimi rzeczami zawraca głowę. Być może jednak potrzebujesz ekstremalnej wydajności lub jesteś jej zwykłym fanatykiem (tak jak ja swego czasu :) ). Jest sposób na zlikwidowanie dodatkowego obciążenia.

Kluczem do sukcesu jest fakt, że przekierowanie w .htaccess, którego używasz (zakładam, że używasz bo inaczej nie uzyskałbyś nawet adresu example.com/artykuly/1,jakis-adres/ a co najwyżej jakieś example.com/artykuly.php/1,jakis-adres/) aby mieć przyjazne URL'e, działa tylko wtedy jeżeli nie istnieje fizycznie na dysku katalog/plik odpowiadający wpisanemu adresowi. Innymi słowy, jeżeli w publicznym katalogu głównym naszej aplikacji istnieje katalog artykuly a w nim katalog jakis-adres to żadne przekierowanie z .htaccess nie zadziała tylko Apache zacznie szukać w tym katalogu jakiegoś pliku index do wyświetlenia/uruchomienia.

Od tej wiedzy do sukcesu już krótki odcinek. Wystarczy podczas tworzenia artykułu (ale nie zapomnij potem o edycji i usuwaniu) tworzyć katalogi, które będą odpowiednikami adresów na stronie. W każdym z takich katalogów wystarczy umieścić plik index.php. Jego zawartość może wyglądać tak:

PHP:
  1. <?php
  2. $id = 1;
  3.  
  4. require '../../../start.php';
  5. start($id);

Oczywiście kod jest zupełnie przykładowy, chodzi o samą logikę. W wygenerowanym pliku mamy informację o identyfikatorze. Dzięki temu nie trzeba robić dodatkowego zapytania do bazy danych. Następnie startujemy naszą aplikację i przekazujemy dalej informację o identyfikatorze.

A więc mamy katalog /artykuly/jakis-adres/ w którym znajduje się plik index.php z powyższą zawartością. Działa. Osobiście przenoszę jeszcze wszystkie wygenerowane katalogi do jakiegoś wspólnego miejsca np. katalogu /cache. To wprowadza mi pewien porządek na dysku serwera, zwłaszcza gdy elementów korzystających z tego mechanizmu jest więcej (miałbym wtedy katalogi artykuly, galeria, imprezy itd. co wprowadza niepotrzebny bałagan). Robię to za pomocą .htaccess. Przykład:

CODE:
  1. RewriteRule ^artykuly/([^/]+)/?$ cache/artykuly/$1/

I w ten oto prosty sposób mamy trochę więcej katalogów i plików na dysku ale:
- zyskaliśmy piękne adresy URL
- cały mechanizm nie generuje zbędnego obciążenia
- sposób nie jest zbyt kłopotliwy bo cały cache siedzi sobie w jednym katalogu i nikomu nie przeszkadza
- nasza strona jest o jeden krok bliżej do osiągnięcia sytuacji gdy artykuły są dostępne nawet podczas awarii bazy danych

Podsumowując: gdy ktoś wpisze adres example.com/artykuly/jakis-adres/ to zadziała przekierowanie na katalog /cache/artykuly/jakis-adres/ gdzie wygenerowany plik index.php posiada informację o identyfikatorze tego katalogu, uruchomi naszą aplikację i przekaże jej ID.

Można jeszcze dopisać mechanizm, który zablokuje bezpośredni dostęp do plików cache na serwerze (aby nie działały adresy example.com/cache/artykuly/jakis-adres/). I na tym koniec :)

PS
Pamiętaj aby pilnować przy adresach bez identyfikatorów aby adresy się nie powtarzały.


Szachy online z otwartym źródłem

26 września 2011

Przeglądając github.com w poszukiwaniu czegoś na czym mógłbym podszkolić się z Symfony 2 natknąłem się na ciekawy projekt. Ktoś stworzył aplikację (PHP5 + JS + HTML5) do gry w szachy i udostępnił całe źródło. Co prawda wygląda na to, że sam silnik odpowiedzialny za grę nie jest napisany w PHP "ale też jest zajebiście", cytując klasyka ;)

Projekt nazywa się lichess i jest naprawdę imponujący, zwłaszcza biorąc pod uwagę, że jest prowadzony przez jedną osobę. Szczegóły techniczne:

- PHP 5.3.2, użyto frameworka Symfony 2
- JavaScript (jQuery i jQuery UI)
- HTML5 i CSS
- "mózg" gry to Crafty Chess
- pgn4web służy do podglądu gier. Daje możliwość osadzania rozgrywek na stronie www, w prostej i miłej formie miniatury, bazuje na JavaScript.

Możliwości jakie aplikacja udostępnia graczowi są co najmniej wystarczające. Możemy grać z innymi ludźmi lub z komputerem (dla komputera wybieramy jeden z ośmiu poziomów trudności). Wybieramy między grą standardową a Chess960. Decydujemy także czy gramy z zegarem.

Każda gra ma swój unikalny adres. W ten sposób rozgrywkę może śledzić więcej osób a po rozegranej grze można prześledzić wszystkie ruchy i zobaczyć cały zapis rozgrywki. Dostępny jest katalog wszystkich rozgrywanych w tej chwili i wcześniej rozegranych gier.

Dzięki zastosowaniu JS i HTML5 gra się bardzo przyjemnie, przeglądarka w żaden sposób nas nie ogranicza. Funkcji jest wiele, nie będę ich wszystkich wymieniał. Jeszcze więcej jest planów, które autor przedstawia na liście TODO.

Twórca zapowiada, że cały projekt będzie zawsze darmowy, open source a strona gdzie można wszystko wypróbować (lichess.org) będzie zawsze wolna od reklam. Kimkolwiek jest, jestem pod wrażeniem jego pracy. Na pewno prześledzę kod PHP, to jest z pewnością nieocenione źródło wiedzy podczas nauki Symfony 2.


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


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.