‘ Tworzenie stron www ’ Kategoria archiwum

Domyślne style w Firefox

01 listopada 2011

W Internecie cały czas trwa dyskusja czy strony www muszą wyglądać identycznie we wszystkich przeglądarkach czy może nie powinniśmy skupiać się na robieniu kopii co do każdego piksela i pozwolić na lekkie różnice.

O problemie pisałem już w tekście "Reset styli CSS" gdzie opowiedziałem się za standaryzacją domyślnych ustawień przeglądarek. Czasami po prostu strona musi wyglądać identycznie aby wszystkie efekty, animacje etc. działały jak należy. Dla mnie ta cała dyskusja jest niezrozumiała.

Piszę to wszystko bo ostatnio napotkałem na dziwny problem z przeglądarką Firefox. Tak, o dziwo nie tylko IE w dzisiejszych czasach potrafi coś spartolić :) Otóż FF dodaje do przycisków formularzy (buttom, submit itp.) wewnętrzny margines. Zresztą sami zobaczcie:

CSS:
  1. button::-moz-focus-inner,
  2. input[type="reset"]::-moz-focus-inner,
  3. input[type="button"]::-moz-focus-inner,
  4. input[type="submit"]::-moz-focus-inner,
  5. input[type="file"]> input[type="button"]::-moz-focus-inner {
  6.   padding: 0px 2px 0px 2px;
  7.   border: 1px dotted transparent;
  8. }

Ustawianie własnego padding nic nie pomaga o ile nie użyjemy tego pięknego "::-moz-focus-inner". I skąd webmasterzy mają o tym wiedzieć? :/

W porównaniu do lat gdy zaczynałem zabawę z HTML (chyba rok 1999) mamy teraz piękne czasy. Mimo to nadal nie jest idealnie i mam duże wątpliwości czy kiedyś będzie.

Listę domyślnych styli CSS w Firefox znajdziemy wpisując w okno przeglądarki taki adres: resource://gre-resources/forms.css

Pod tym adresem znajduje się oficjalny arkusz CSS dla elementów języka HTML 4. Natomiast tutaj jest nieoficjalny (oficjalnego nie mogłem znaleźć) kod CSS dla HTML 5.


Optymalizacja plików PNG

25 października 2011

"Tnąc" grafikę do HTML/CSS często też zwracamy uwagę na rozmiary zapisanych plików. I tak na przykład w formacie JPG sprawa jest jasna. Jest to format z kompresją stratną i sami ustalamy gdzie leży granica między rozmiarem a jakością. Pliki GIF używają kompresji bezstratnej (algorytm LZW i jego pamiętne patenty...) ale format ten obsługuje jedynie 256 kolorów więc następuje kwantyzacja kolorów i rozmiary tych plików są niewielkie (co było istotne w latach 80. i 90.). A co z PNG?

PNG powstał jako odpowiedź na GIF i problemy pantentowe. Jest to format kompresji bezstratnej i teoretycznie powinniśmy się spodziewać, że eksport do PNG da zawsze takie same lub przynajmniej bardzo podobne rozmiary plików. W praktyce, podczas zapisywania pliku, następują pewne przekształcenia. Można je wykonać mniej lub bardziej dokładnie co ma wpływ na dwa czynniki: czas generowania się pliku wynikowego i jego rozmiar.

Niestety wiele programów graficznych nie traktuje problemu zbyt poważnie i lecą po linii najmniejszego oporu. Efektem są pliki o zbyt dużych rozmiarach.

Od kilku lat stosuję z powodzeniem program OptiPNG. Dzisiaj ze zdumieniem odkryłem, że jego początki sięgają grudnia 2001.

Program daje pozorny wybór stopnia kompresji. Nie działa to oczywiście tak jak w JPG. Jest to po prostu kompromis jaki sami ustalimy między dokładnością a czasem. Im dokładniej tym dłużej ale tym także mniejszy rozmiar pliku.

Dla programu istnieją różne dodatki/nakładki. Testowałem OptiPNG-UI. Program nie jest najładniejszy ale nie trzeba wszystkiego robić z linii poleceń co jest zbawienne przy większej ilości plików. Domyślnie wszystko jest po włosku. Aby to zmienić należy kliknąć na niebieską strzałkę w prawym górnym rogu i w nowo otwartym oknie wybrać jakąś flagę (dostępne języki: włoski, angielski, hiszpański, francuski).

Optymalizujcie swoje grafiki, stosujcie też technikę CSS Sprites (którą w pewnym stopniu opisałem tutaj). To wszystko daje wymierne efekty.


Połączenie AJAX z obcą domeną za pomocą jQuery

22 października 2011

AJAX to wspaniała technologia dzięki której mogło powstać wiele rewolucyjnych usług. Ma ona jednak pewne ograniczenia związane z polityką bezpieczeństwa przeglądarek. Jednym z największych ograniczeń jest możliwość łączenia się poprzez AJAX wyłącznie ze stronami w tej samej domenie. Krótko mówiąc, nie ma możliwości pobrać strony example2.com ze strony example1.com. Tak przynajmniej myślałem do tej pory :)

Nim jeszcze przejdę do meritum sprawy, dodam, że oczywiście istnieje obejście problemu. Można napisać swego rodzaju proxy w PHP lub w innym języku i za pomocą tego proxy pobierać docelową stronę. Trzeba jednak koniecznie pamiętać aby przy tego typu rozwiązaniach jakoś filtrować kto korzysta z naszego skryptu i co pobiera. Inaczej będą problemy bo skrypt musi być przecież publicznie dostępny.

Nam jednak zależy aby całą sprawę załatwić z poziomu JavaScript. Z pomocą przychodzi YQL od Yahoo!.

Czym jest YQL? W dużym uproszczeniu, jest to język składniowo podobny do SQL, który pozwala na odczyt/manipulację różnymi zorganizowanymi strukturami danych np. HTML. Jego możliwości możemy wykorzystać dla własnych celów o czym możemy się dowiedzieć z tego artykułu. Pozwolę sobie skopiować jeden przykład:

JavaScript:
  1. $(document).ready(function(){
  2. var container = $('#target');
  3. $('.ajaxtrigger').click(function(){
  4. doAjax($(this).attr('href'));
  5. return false;
  6. });
  7. function doAjax(url){
  8. // if it is an external URI
  9. if(url.match('^http')){
  10. // call YQL
  11. $.getJSON("http://query.yahooapis.com/v1/public/yql?"+
  12. "q=select%20*%20from%20html%20where%20url%3D%22"+
  13. encodeURIComponent(url)+
  14. "%22&format=xml'&callback=?",
  15. // this function gets the data from the successful
  16. // JSON-P call
  17. function(data){
  18. // if there is data, filter it and render it out
  19. if(data.results[0]){
  20. var data = filterData(data.results[0]);
  21. container.html(data);
  22. // otherwise tell the world that something went wrong
  23. } else {
  24. var errormsg = '<p>Error: could not load the page.</p>';
  25. container.html(errormsg);
  26. }
  27. }
  28. );
  29. // if it is not an external URI, use Ajax load()
  30. } else {
  31. $('#target').load(url);
  32. }
  33. }
  34. // filter out some nasties
  35. function filterData(data){
  36. data = data.replace(/<?/body[^>]*>/g,'');
  37. data = data.replace(/[r|n]+/g,'');
  38. data = data.replace(/<--[Ss]*?-->/g,'');
  39. data = data.replace(/<noscript[^>]*>[Ss]*?</noscript>/g,'');
  40. data = data.replace(/<script[^>]*>[Ss]*?</script>/g,'');
  41. data = data.replace(/<script.*/>/,'');
  42. return data;
  43. }
  44. });

To kompleksowy kod, który pozwala stworzyć proste odnośniki na stronie służące do pobierania zewnętrznych witryn, przy okazji filtrując wyniki z potencjalnie niebezpiecznego kodu. Dobrze wiedzieć, że YQL pobiera tylko zawartość tagu body docelowej strony, co ma oczywiście swoje konsekwencje np. dostaniemy dostęp tylko do tych styli CSS, które zostały bezpośrednio "wpisane" w tagi HTML, tzw. inline CSS.

Pod tym adresem znajduje się prezentacja działania tego kodu.

Na github.com znajduje się również prosty skrypt jQuery, który szalenie upraszcza korzystanie z dobrodziejstw YQL. Dzięki niemu możemy korzystać z dotychczasowych rozwiązań opartych o AJAX i podawać zewnętrzne adresy www a skrypt sam martwi się już o to aby cały proces przebiegł bez problemów. Przykład użycia (z tej strony):

JavaScript:
  1. $('#container').load('http://google.com'); // SERIOUSLY!
  2.  
  3. $.ajax({
  4.     url: 'http://news.bbc.co.uk',
  5.     type: 'GET',
  6.     success: function(res) {
  7.         var headline = $(res.responseText).find('a.tsh').text();
  8.         alert(headline);
  9.     }
  10. });

Warto wspomnieć o alternatywnej metodzie. Istnieją rozwiązania w których JS łączy się z odpowiednim plikiem Flash i to on wykonuje za nas robotę polegającą na pobraniu zawartości strony. Ograniczeniem tej metody jest fakt, że komunikacja nie może być zablokowana na domenie docelowej w pliku crossdomain.xml. Popularnym skryptem rozwiązującym problem właśnie za pomocą Flash'a jest flXHR.

Kłopot z tzw. cross-domain AJAX jest obszerny, mam za małą wiedzę aby móc go lepiej opisać. Żywię jednak nadzieję, że tekst będzie przydanty i pomoże komuś rozwiązać jego problemy. Zachęcam do samodzielnego zgłębiania problemu i dzielenia się wiedzą w komentarzach.

PS
Pytanie za 100 punktów. Skoro AJAX nie pozwala pobierać danych z zewnętrznych adresów www to jakim cudem pozwala łączyć się z domeną http://query.yahooapis.com/ ? Pytam szczerze bo ja tego nie wiem :) Firebug nie pokazuje ruchu generowanego za pomocą tego rozwiązania jako ruch AJAX tylko przypisuje go do zakładki JS.

EDIT
Czytaj komentarze, koledzy dali tam wiele interesujących, uzupełniających informacji!


Bootstrap od Twitter

13 października 2011

Twitter wypuścił jakiś czas temu w świat całkiem ciekawy twór, który zwie się Bootstrap. Można go chyba zaliczyć do frameworków CSS chociaż korzysta też z możliwości JavaScript.

Nie zdołałem się jeszcze przekonać do takich produktów jak Blueprint (3 i pół roku temu zamieściłem nawet krótki wpis informacyjny o tym frameworku, tutaj link) czy 960 Grid System. Niby znam ich zalety ale jakoś brakuje czasu i energii żeby wreszcie któryś poznać. Chyba nie leży mi przede wszystkim idea budowania CSS na bazie siatki. Może kiedyś będzie okazja się przemóc i spróbować któregoś rozwiązania.

Bootstrap wpadł mi jednak w oko. Może dlatego, że jego dokumentacja (tak, to ten sam link co wcześniej :) ) jest tak banalna, przejrzysta i przyjazna, że każdy złapie w lot jak go używać.

Bootstrap to zbiór bibliotek CSS wzbogacony o LESS (napiszę o tym więcej, obiecuję!) i pluginy JavaScript. Razem prezentuje się to naprawdę atrakcyjnie i prosto. Wystarczy spojrzeć na przykłady z dokumentacji. Typografia, przyciski, formularze, okienka. Wszystko to i wiele więcej, gotowe do użycia, często bez naszej ingerencji, czasami wymaga tylko dodania odpowiedniej klasy do elementu.

Raczej to nie jest jeszcze ten moment gdy zbuduję pierwszą stronę w całości opartą o framework CSS jednak Bootstrap idealnie pasuje mi do tworzenia różnego rodzaju paneli administracyjnych. Z wyglądem takich paneli zawsze jest problem a tutaj mamy wszystko gotowe.

Polecam Bootstrap, warto też bliżej przyjrzeć się dostępnym pluginom JavaScript (oparte o mój ulubiony famework JS czyli jQuery) i podejrzeć trzy przykładowe strony (pierwsza, druga, trzecia).

Źródła dostępne są do ściągnięcia na GitHub pod adresem https://github.com/twitter/bootstrap.


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.


Parsowanie kodu CSS w PHP

23 września 2011

Zdarza się czasami, że musimy wykonać jakąś bardzo specyficzną pracę programistyczną. Mi to się niestety zdarza aż za często :) Tak było i tym razem. Musiałem zamienić pobrany kod CSS na coś bardziej strawnego, najlepiej na tablicę PHP. Przy tego typu zadaniach dobrze jest zacząć od Google, znaleźć rozwiązanie, użyć i zapomnieć. Niestety z tym znajdowaniem nie zawsze jest tak różowo...

Przeszukałem dość dokładnie Internet pod kątem parsowania kodu CSS w PHP. Znalazłem kilka, może kilkanaście rozwiązań ale z większością z nich były jakieś problemy. Skoro już przez to przeszedłem to chyba dobrze byłoby napisać o tym kilka słów i zaoszczędzić innym nieszczęśliwcom trochę pracy.

Zacznę od prostego, anonimowego kawałka kodu, który znalazłem gdzieś w sieci. Po lekkich poprawkach prezentuje się w taki sposób:

PHP:
  1. function parse_css($css) {
  2.  
  3.   preg_match_all('/(?ims)([a-z0-9\s\.\:#_\-@]+)\{([^\}]*)\}/si', $css, $parsed);
  4.  
  5.   $result = array();
  6.  
  7.   if(isset($parsed) AND !empty($parsed) AND isset($parsed[0]) AND !empty($parsed[0]) AND isset($parsed[1]) AND !empty($parsed[1]) AND isset($parsed[2]) AND !empty($parsed[2])) {
  8.  
  9.     foreach($parsed[0] AS $key => $value) {
  10.  
  11.     if(isset($parsed[1][$key]) AND isset($parsed[2][$key])) {
  12.  
  13.         $selector = trim($parsed[1][$key]);
  14.        
  15.         if($selector != '') {
  16.           $rules = explode(';', trim($parsed[2][$key]));
  17.  
  18.           if(!empty($rules)) {
  19.             if(!isset($result[$selector])) {
  20.               $result[$selector] = array();
  21.             }
  22.  
  23.             foreach($rules AS $rule) {
  24.  
  25.               if(!empty($rule)) {
  26.                 $rule = explode(':', $rule);
  27.  
  28.                 if(isset($rule[0]) AND $rule[0] != '' AND isset($rule[1]) AND $rule[1] != '') {
  29.                
  30.                   $rule[0] = trim($rule[0]);
  31.                   $rule[1] = trim($rule[1]);
  32.                  
  33.                   if($rule[0] != '' AND $rule[1] != '') {
  34.                     $result[$selector][trim($rule[0])] = trim($rule[1]);
  35.                   }
  36.                 }
  37.               }
  38.             }
  39.           }
  40.         }
  41.       }
  42.     }
  43.   }
  44.  
  45.   return $result;
  46. }

Kod jest naprawdę prosty a efektem jego działania jest ładna tablica wielowymiarowa PHP z kluczami głównymi jako selektory CSS do których są przypisane pary właściwość <-> wartość.

Na tym właściwie mógłbym zakończyć tego newsa ale zdaję sobie sprawę, że niektórzy mogą mieć inne/większe potrzeby dlatego teraz krótki przegląd rozwiązań:

  • CSSTidy - Rozbudowane narzędzie, dostępne w dwóch postaciach: plik wykonywalny EXE oraz aplikacja PHP. Głównym zadaniem CSSTidy jest tak przerobić dany kod CSS aby zmniejszyć jego objętość wywalając niepotrzebne fragmenty i poprawiając niektóre definicje. Dostępna jest również kompresja kodu. Oczywiście aby wykonywać takie czynności, potrzebny jest rozbudowany parser CSS :) Osobiście go nie testowałem dlatego chętnie przeczytam każdą opinię. PS: Autorzy na stronie chwalą się, że nie użyli żadnych wyrażeń regularnych.
  • PHP CSS Parser - Nie testowałem ale wygląda na całkiem rozbudowany parser CSS, w wygodnej, obiektowej formie. Przyda się szczególnie tym, którzy nie tylko chcą coś z kodu CSS odczytać ale również go zmodyfikować.
  • PEAR HTML_CSS - Z PEAR praktycznie nigdy nie korzystałem, jakoś nie było potrzeby, nie mogłem się do tego przekonać... Z opisu wygląda zachęcająco. Nic więcej o tym nie mogę napisać ale mimo to umieszczam na liście bo część z Was na pewno ma duże zaufanie do PEAR.
  • CSS parser - Prosta i przyjemna w użyciu klasa za pomocą której łatwo wyciągniemy informacje jaka wartość została przypisana do właściwości dla danego selektora. Martwi mnie jedynie wiek tego kodu (rok "produkcji": 2003) i lista tagów HTML w źródle, która jest niepełna i na nasz grzbiet spadnie obowiązek jej uzupełnienia i aktualizowania w przyszłości.
  • CssMin - Oprogramowanie nastawione przede wszystkim na "kompresję" styli CSS ale z krótkiej analizy kodu wnioskuję, że używa bardzo ładnego i rozbudowanego parsera CSS. Chętnie przeczytam opinię jak to działa jeżeli ktoś pokusi się o testy/użycie ;)

Oprócz tej krótkiej listy istnieją oczywiście inne rozwiązania. Szczególnie sporo jest malutkich parserów zrzucających CSS do tablicy PHP ale kod przedstawiony przeze mnie powyżej sprawdza się wyśmienicie dlatego chyba można sobie darować inne klony.

Na koniec dodam, że warto przed obróbką parserem usunąć z kodu CSS wszelkie komentarze. Pewnie te bardziej zaawansowane parsery same się tym martwią ale te mniej rozbudowane już niekoniecznie. Oto kod:

PHP:
  1. $css = preg_replace('!/\*.*?\*/!s', '', $css);
  2. $css = preg_replace('/\n\s*\n/', "\n", $css);


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...


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! :)