Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 07.03.2011 23:09, tagi: php

Jak głosi stare przysłowie lansowane przez pewne grono uczonych programistów – „należy co roku uczyć się nowego języka programowania”. Jakiś czas temu stworzyłem cykl artykułów o tworzeniu prostej dynamicznej strony www opartej o Pythona i mod_wsgi. Rok raczej nie minął, co nie oznacza, że nie nadszedł czas na poszerzenie swoich horyzontów myślowych i zaopatrzenie się w nowe zabawki :) .

Językiem, który zamierzam wałkować przez kilka następnych wpisów jest Scala – język obiektowo – funkcyjny działający na platformie JVM oraz .Net . Zainteresowanie tym językiem zrodziło się u mnie pewnego czasu, gdy znudzony klepaniem kolejnego banalnego portalu w PHP zacząłem sobie wyobrażać jak powinien wyglądać idealny język programowania. Owe przemyślenia poskutkowały wertowaniem Wikipedii i czytaniem o różnych dziwnych językach, paradygmatach i technologiach. W czasie moich poszukiwań natrafiłem właśnie m.in na Scalę. Zainteresowała mnie w niej jej funkcyjna natura oraz ciekawe własności obiektowe.

Zanim przejdę do kolejnych części wpisu by przedstawić Wam ten wspaniały język, zamierzam przedstawić jak krok po kroku przygotować sobie wygodne środowisko programistyczne.

Jako IDE, którego będę używał wybrałem Netbeans. Korzystam z niego już od dłuższego czasu (z przerwą na testowanie PHPStorm poleconego przez szanownego Batmana) . Posiada ono wsparcie dla Scali i zamierzam z niego skorzystać.

Proces przygotowania środowiska omawiam z założeniem, że osoba czytająca artykuł ma zainstalowane Netbeans w wersji z wsparciem dla PHP. Dlaczego ? Tak jest trudniej ;P

  • Jeżeli jeszcze nie mamy zainstalowanego, ściągamy JDK ze strony Oracle’a.
  • Ściągamy kompilator Scali, wraz z bibliotekami z jej strony
  • Rozpakowujemy ściągnięte archiwum do dowolnego katalogu (nie powinien zawierać spacji), u mnie C:/Program Files/Scala (a jednak spacje są :P )
  • Ustawiamy zmienną środowiskową SCALA_HOME na wybrany wcześniej katalog
  • Dodajemy do systemowej zmiennej PATH, katalog SCALA_HOME/bin
  • Ściągamy i rozpakowujemy wtyczkę do Netbeans do dowolnego katalogu
  • Otwieramy plik katalog_instalacyjny_netbeans/etc/netbeans.conf i dopisujemy do zmiennej netbeans_default_options następujący tekst: -J-Dscala.home=katalog_ze_scalą
  • Otwieramy Netbeans, wchodzimy w Tools->Plugins->Downloaded->Add plugins i dodajemy rozpakowane przez nas pliki wtyczkowe
  • Jeżeli podczas instalacji wtyczek Netbeans marudził by coś o braku JDK, należy otworzyć plik netbeans_default_options i ustawić zmienną netbeans_jdkhome na naszą lokalizację JDK
  • By przetestować, wystarczy utworzyć nowy przykładowy projekt File->New Project->Scala->Scala Application i po utworzeniu nacisnąć „play”, jeżeli wszystko zrobiliśmy dobrze to efektem działania w okienku dolnym powinien być napis „hello world”

To będzie na tyle dzisiaj jeżeli chodzi o Scalę. Zapraszam na kolejne części cyklu i liczę na Wasze komentarze i uwagi ;)

Autor wpisu: batman, dodany: 07.03.2011 08:30, tagi: jquery, php

jFromer to kolejny interesujący projekt zbudowany na bazie jQuery. Tym razem nie jest to tylko JavaScript. Twórcy jFormer poszli o krok dalej i skorzystali z pomocy PHP, przy pomocy którego generowany jest formularz. Z dostępnych funkcjonalności można wymienić walidację formularza po stronie klienta oraz serwera, czy też przetwarzanie formularza przy pomocy AJAXa. warto również wspomnieć o gotowych szablonach dla najpopularniejszych typów formularzy, ochronie przed robotami oraz możliwości modyfikacji wyglądu formularzy przy użyciu CSS.

Zainteresowanych jFormerem odsyłam do strony projektu – www.jformer.com, a niezdecydowanych do zapoznania się z przykładowymi formularzami – www.jformer.com/demos. Przykładowy kod znajdziecie w dokumentacji – www.jformer.com/documentation.

Autor wpisu: cojack, dodany: 06.03.2011 15:37, tagi: php, sql

PHP Wczoraj pracowałem nad swoim Frameworkiem, miałem kłopot jakby sobie tu poradzić z parametrami przesyłanymi do procedur w funkcjach SQL, gdyż w każdym engine pl/sql mogą one różnie wyglądać, więc poszedłem po rozum do głowy użyłem pseudo Dekoratora działającego na małej fabryce, tylko zaś ten dekorator nie jest typową implementacją książkową. No ale dobra, do rzeczy. Problem był z utworzeniem tablicy PostgreSQL z tablicy PHP, i do jasnej cholery nie udało mi się rozwikłać tego problemu bez użycia rekurencji. Z tego powodu jestem bardzo niezadowolony, gdyż tak bardzo chciałem nie używać rekurencji w swoim kodzie, dobra stało się, może teraz słów kilka o tym typie tablicy w PostgreSQL?

Array Postgresql

Jak wiemy w php mamy tablice asocjacyjne, takich w postgresql nie ma, to jak sobie poradzić z danymi przesyłanymi do funkcji, by wiedzieć która wartość odpowiada któremu rekordowi w bazie? Trzeba przyjąć sobie jakiś schemat i się jego trzymać, nauczyłem się tego pracując wcześniejszej firmie, z czego jestem bardzo zadowolony i cenie sobie tą wiedzę do której doszedłem sam. Ale się nią z Wami podzielę.

Przykład tablicy w PostgreSQL: ‘{1234,325,513,1332}’, jest to zwykła tablica jednowymiarowa, w php zapisalibyśmy ją tak: $someArray = array(1234,325,513,1332);

Więcej tutaj: link

Przykład z życia

Proste oczywiste, nie stwarzającego żadnego problemu do odczytania. Z tym że takie tablice są rzadkością. Przeważnie operujemy na rekordach z tabeli, które posiadają unikatowy identyfikator w bazie, i właśnie on jest nam potrzebny. Jeżeli mamy pola wielokrotnego wyboru, np checkboxy, teoria, relacja jeden do wielu, jeden produkt może należeć do wielu kategorii w sklepie. No to przykład kawałka kodu html:

<label>Jakaś kategoria</label>
<input type="checkbox" name="categories[$incramentValue][id_category]" value="$jakies_id_kategorii" />
<label>Rabat dla kategorii tego produktu</label>
<input type="text" name="categories[$incramentValue][discount]" value="$jakas_wartosc_rabatu" />

To akurat jest trochę bardziej rozbudowany przykład niż ten o który mi chodziło ;d Gdyż gdybyśmy mieli tylko zwykłe przypisanie produktu do kategorii, to wystarczyło by naszej funkcji w sql 2 parametry, jeden to id produktu, a drugi to tablica z idkami kategorii, które wybraliśmy. No ale dobra, jeżeli chcemy operować czasami na paru tabelach w jednym widoku, to takie rozwiązanie jest jak najbardziej zrozumiałe, i teraz w naszej tablicy po przesłaniu do php będziemy mieli coś takiego:

array(
  $incramentValue = array(
    'id_category' => $jakies_id_kategorii,
    'discount' => $jakas_wartosc_rabatu
  )
  ... itd
)

Jak to ugryźć?

No i dobra, teraz tak mamy identyfikator kategorii i rabat jaki chcemy nadać temu produktowi w tej kategorii, można by tam jeszcze dorzucić id klienta, taki pełny system b2b (business-to-business). Mamy to co mamy, teraz tak jak pisałem już wyżej, musimy sobie przyjąć jakiś standard w sql którym w danej funkcji będziemy operować na tych tablicach, widząc po kolejności argumentów w tablicy wiemy jak byśmy chcieli by wyglądała nasza tablica w SQL, o tak: ‘{{$jakies_id_kategorii,$jakas_wartosc_rabatu},{$jakies_id_kategorii2,$jakas_wartosc_rabatu2},{…}}’ czyli np: ‘{{2,34.2},{5,12}}’. Po przesłaniu takiej tablicy do procedury w SQL musimy ją jeszcze tylko „przelecieć” i wstawić odpowiednie rekordy, a jak utworzyć taką tablicę?

Utworzenie tablicy PostgreSQL z tablicy PHP

Napisałem do tego funkcję:

   function phpArrayToPg( array $phpArray, $inner_glue = ',' ) {
      foreach( $phpArray as $key => $value ) {
         if( is_array( $value ) ) {
            $output[$key] = "{".phpArrayToPg($value, $inner_glue)."}";
         }
         else {
            if( !(int)$value )
               $output[$key] = '"'.$value.'"';
            else
               $output[$key] = (int)$value;
         }
      }
 
      return implode( $inner_glue, $output );
   }

Która się nie podoba depeszowi ;d Dlaczego? Pytał się mnie co z wartościami które będą posiadały w sobie jakieś nietypowe wartości, czyli np: ‘, \, / itp znaki escape, szczerze to mało mnie interesują takie wartości, dlaczego? Używam PDO do bindowania takich wartości, to że w stringu będzie ‘ czy \ czy ¬ a nawet ¿ jest mi to totalnie obojętne, znaki te nie wyescepują zapytania i to jest najważniejsze, a jak strzelę gafę przy validacji podczas wprowadzania wartości przez użytkowników to jest już tylko i wyłącznie mój błąd a nie że funkcji która ma na celu tylko utworzenie tablic z tablicy.

Wywołanie:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Piotr Śliwa, dodany: 06.03.2011 00:13, tagi: php, symfony

Jedną z najbardziej podstawowych zasad programowania zorientowanego na obiekty to hermetyzacja danych. Mechanizmy php dostarczają nam modyfikatory dostępu, które to pomagają nam w hermetyzowaniu danych i implementacji poszczególnych klas, tak abyśmy mieli swobodę we wprowadzania zmian, które nie zmieniają funkcjonalności. API to interfejs, który nie ukrywamy, a udostępniamy. Co więc składa się na ten interfejs?

Na API klasy składają się:

  • składowe i metody publiczne
  • stałe
  • składowe i metody chronione, jeśli klasa jest przeznaczona do dziedziczenia (nie jest klasą finalną)
  • postać serializowana

Dwa pierwsze punkty wydają się oczywiste, API jest interfejsem obiektu, z którego może korzystać klient (czyli obiekt pracujący na innym obiekcie udostępniającym to API). Dwa pozostałe punkty nie wydają się tak oczywiste. Dla wyjaśnienia trzeciego punktu posłużę się przykładem z symfony 1.4.x:

[PHP]
  1. abstract class sfComponent
  2. {
  3. protected
  4. $moduleName = '',
  5. $actionName = '',
  6. $context = null,
  7. $dispatcher = null,
  8. $request = null,
  9. $response = null,
  10. $varHolder = null,
  11. $requestParameterHolder = null;
  12.  
  13. //ciach...
  14. }

Co by się stało gdyby developerzy symfony postanowili zmienić nazwę składowej $varHolder na np. $dataForView lub też typ przechowywany przez tą składową? Wiele projektów, które korzystają bezpośrednio z niej przestała by działać. Ustawiając tą składową jako chronioną sami siebie ograniczyli co do jej typu (klasy dziedziczące po sfComponent i pracujące bezpośrednio na $varHolder oczekują interfejsu jaki udostępnia klasa sfParameterHolder) oraz jej nazwy. Powyższa klasa udostępnia również rozmaite metody ustawiające, które operują na składowej $varHolder (getVar, setVar oraz magiczne metody __get, __set, __isset, __unset), które wyczerpują zastosowanie tej składowej. Klasa ta wcale nie ukrywa danych i swojej implementacji. Dlaczego składowa $varHolder oraz reszta składowych są chronione? Zapewne z przyzwyczajenia programisty lub też konwencji przyjętych przez zespół, dla dużej liczby programistów "podstawowym" modyfikatorem dostępu jest modyfikator chroniony, przez co klasy udostępniają za dużo informacji niż powinny, a co za tym idzie niepotrzebnie udostępniają większe, bardziej skomplikowane i naszpikowane szczegółami API. Ewentualna refaktoryzacja takiej klasy jest ograniczona, gdyż może już istnieć wiele kodu, który korzysta z jej szczegółów implementacyjnych. Wniosek jest taki, że nie należy bezmyślnie ustawiać wszystkim właściwościom modyfikatora chronionego, ale używać tego modyfikatora tam gdzie faktycznie jest on niezbędny. Taka sytuacja może mieć miejsce, gdy składowa jest prywatna i ma np. chronione metody ustawiające i pobierające, przez co sama prosi się o większą widoczność.

Podobna sytuacja ma się z metodami, jednakże modyfikator "chroniony" powinien być bardziej powszechny wśród metod, gdyż dane powinny być chronione w większym stopniu.

Ostatni składnik API, czyli postać serializacji jest pewnie największym zaskoczeniem. Pamiętajmy że dzięki mechanizmie serializacji można ustawić i odczytać prywatną właściwość obiektu. Domyślna postać serializacji udostępnia mnóstwo szczegółów na temat implementacji klasy.

[PHP]
  1. class A
  2. {
  3. private $objectOfB;
  4.  
  5. public function __construct(B $objectOfB)
  6. {
  7. $this->objectOfB = $objectOfB;
  8. }
  9. }
  10.  
  11. class B
  12. {
  13. private $text;
  14.  
  15. public function __construct($text)
  16. {
  17. $this->text = (string) $text;
  18. }
  19. }
  20.  
  21. $a = new A(new B('some text'));
  22.  
  23. echo serialize($a);

Wynik powyższego kodu będzie: O:1:"A":1:{s:12:"?A?objectOfB";O:1:"B":1:{s:7:"?B?text";s:9:"some text";}}

Widać więc, że klasa A ma właściwość prywatną o nazwie "objectOfB", której wartością powinien być obiekt klasy B. Mozna zmodyfikować tą postać serializowaną, przez co jawnie ustawimy wartość prywatnej składowej deserializowanego obiektu: O:1:"A":1:{s:12:"?A?objectOfB";s:9:"some text"}. Teraz gdy to zdeserailizujemy, w składowej "objectOfB" będzie przechowywany ciąg znaków - zostanie złamany niezmiennik obiektu, który zakłada (za pomocą konstruktora) że przechowuje ona obiekt typu B.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: batman, dodany: 04.03.2011 08:00, tagi: zend_framework

Najpopularniejszym i póki co najskuteczniejszym zabezpieczeniem przed spamowaniem naszych formularzy jest captcha. Zend Framework, aspirujący do miana najkompletniejszej biblioteki dla języka PHP, dostarcza komponent Zend_Captcha, który w prosty sposób integruje się z formularzem. W kilku prostych krokach jesteśmy w stanie uodpornić nasz formularz na spamujące roboty.

Przed przystąpieniem do konfigurowania captchy, musimy uzbroić się w plik z czcionką, jaka zostanie użyta do utrudnienia życia spamerom. Czcionkę możemy znaleźć np. na stronie Google Web Fonts. Po pobraniu czcionki umieszczamy ją w projekcie. W moim przypadku jest to katalog data znajdujący się na tym samym poziomie co application. Następnie w publicznym katalogu musimy utworzyć katalog na wygenerowane pliki z kodem.

Nadeszła pora na skonfigurowanie captchy.

$captchaImage = new Zend_Captcha_Image();
$captchaImage->setFont(APPLICATION_PATH . '/../data/Kreon-Regular.ttf')
             ->setFontSize(36)
             ->setImgDir(APPLICATION_PATH . '/../public/captcha')
             ->setImgUrl('/captcha')
             ->setExpiration(90)
             ->setGcFreq(5)
             ->setWidth(200)
             ->setHeight(100)
             ->setTimeout(60)
             ->setWordlen(5);

Mimo iż powyższy kod do najpiękniejszych nie należy, doskonale spełnia swoje zadanie. Kolejne metody odpowiadają za:

  • setFont – ustawienie czcionki jaka zostanie użyta na obrazku
  • setFontSize – ustawienie rozmiaru czcionki
  • setImgDir – ustawienie katalogu, w którym będą przechowywane obrazki z kodem
  • setImgUrl – ścieżka do obrazków wstawiana do znacznika img
  • setExpiration – data ważności wygenerowanych plików
  • setGcFreq – ustawienie ilości requestów, po których usunięte zostaną nieaktualne obrazki z kodem
  • setWidth, setHeight – ustawienie szerokości i wysokości obrazka z kodem
  • setTimeout – ustawienie czasu ważności sesji dla aktualnego obrazka z kodem
  • setWordlen – ustawienie ilości liter wyświetlanych na obrazku

Po przebrnięciu przez gąszcz ustawień, możemy przejść do budowania formularza. W tym celu skorzystamy z klasy Zend_Form_Element_Captcha opakowującej stworzą wcześniej captchę w dekoratory formularza oraz ustawiająca odpowiedni walidator.

Całość wygląda następująco.

class Application_Form_Formularz extends Zend_Form
{
    public function init()
    {
        $captchaImage = new Zend_Captcha_Image();
        $captchaImage->setFont(APPLICATION_PATH . '/../data/Kreon-Regular.ttf')
                     ->setFontSize(36)
                     ->setImgDir(APPLICATION_PATH . '/../public/captcha')
                     ->setImgUrl('/captcha')
                     ->setExpiration(90)
                     ->setGcFreq(5)
                     ->setWidth(200)
                     ->setHeight(100)
                     ->setTimeout(60)
                     ->setWordlen(5);

        $captcha = new Zend_Form_Element_Captcha(
            'txt_captcha',
            array(
                'captcha' => $captchaImage
            )
        );

        $this->addElement($captcha);
    }
}

W celach prezentacyjnych ograniczyłem formularz do minimum.

Na koniec ważna uwaga. Jeśli będziecie chcieli modyfikować dekoratory, pamiętajcie, że Zend_Form_Element_Captcha nie korzysta z dekoratora ViewHelper. Zamiast niego należy użyć dekoratora Captcha.

Autor wpisu: sokzzuka, dodany: 03.03.2011 11:51, tagi: php

Moriyoshi Koizumi przedstawił wczoraj popołudniu propozycję wbudowania do php-cli deweloperskiego serwera www. Powstała propozycja RFC wraz z patchem dostępnym na githubie. Jak dotąd propozycja spotkała się z pozytywnym przyjęciem na liście dyskusyjnej.

Ogólnie zamysł jest taki, by można było szybko przygotować sobie środowisko deweloperskie korzystając tylko z dystrybucji PHP, bez konieczności instalowania apache, czy innego webservera. Jest to bardzo podobna strategia, jak ta stosowana np. we frameworku Django dla Pythona. Jak na razie możliwości tej implementacji sprowadzają się do nasłuchiwania na wybranym porcie  żądań od przeglądarki, ustawienia „document roota” i definiowalnego w zewnętrznym pliku php routingu.

Osobiście propozycja mi się bardzo podoba, a jakie jest Wasze zdanie :> ?

Autor wpisu: l3l0, dodany: 03.03.2011 00:03, tagi: php

Przygotowania

Po ostatnim poście, zdecydowałem się lepiej zapoznać Behat-a. Postanowiłem że upiekę dwie pieczenie przy jednym ogniu i od razu zacznę uczyć się Symfony2 (szczególnie że uważam frameworki tego typu za przyszłość PHP). Wybrałem więc do moich niecnych planów BehatBundle z Symfony2. Dwie godziny spędziłem na konfiguracji Symfony2 z BehatBundle oraz Doctrine2 MongoDB ODM. Użyłem sandboxa i zaktualizowałem parę rzeczy ręcznie, jednak opłaciło się bo po tych operacjach zyskałem znakomite środowisko do zabawy.

Zabawę z Behatem czas zacząć

Utowrzyłem wszystkie potrzebne Behatowi katalogi takie jak: src/Sensio/HelloBundle/Tests/Features, src/Sensio/HelloBundle/Tests/Features/steps, src/Sensio/HelloBundle/Tests/Features/support

Tworzenie pliku "feature"

Plik "feature" powinnen być stworzony w formacie "Gherkin" czyli formacie zaczerpniętym z ogórka (Cucumber) który jest napisany w Rubym :P Co ciekawe "Gherkin" pozwala na definiowane plików w różnych językach, między innymi po polsku. Przykładowy plik wygląda tak:

# language: pl

Właściwość: Zmiana danych użytkownika
  Jako użytkownik
  chcę zmienić dane w profilu

  Założenia:
    Zakładając że użytkownik jest "l3l0" w bazie
    I jestem na podstronie /user/profile/l3l0

  Scenariusz: Wypełniam wszystkie potrzebne pola
    Zakładając że wypełniam pole formularza "userProfile[firstname]" wartością "Leszek"
    I wypełniam pole formularza "userProfile[lastname]" wartością "Prabucki"
    I wypełniam pole formularza "userProfile[email]" wartością "leszek.prabucki@gmail.com"
    I wypełniam pole formularza "userProfile[age]" wartością "24"
    I wypełniam pole formularza "userProfile[job]" wartością "PHP developer"
    Jeżeli naciskam guzik "Save" z formularza userProfile
    Wtedy powinien pokazać się tekst "Your details is saved."
    I użytkownik "Leszek" "Prabucki" z mailiem "leszek.prabucki@gmail.com" powinnen zostać utworzony

  Scenariusz: Nie wypełniam wszystkich potrzebnych pól
    Zakładając że wypełniam pole formularza "userProfile[firstname]" wartością "Leszek"
    Jeżeli naciskam guzik "Save" z formularza userProfile;
    Wtedy powinien pokazać się tekst "You should fill all required fields."

Myślę że znaczenie pliku jest dość intuicyjne. Słowka "Scenariusz, Zajaładając, Jeżeli, Wtedy, I, Właściwość" są kluczowymi. Dzięki nim możemy definować swoje własne "kroki".

Jako iż pliki "feature" są testami możemy je uruchamiać. Służy do tego ta komenda:

php app/console behat:test:bundle Sensio\\HelloBundle

W tej chwili dostaniesz pewnie jeszcze błedy, aby to naprawić musimy utworzyć plik src/Sensio/HelloBundle/Tests/Features/support/bootstrap.php z taką treścią:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.