Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

Autor wpisu: batman, dodany: 09.03.2011 08:00, tagi: php

Zgodnie z obietnicą dzisiaj zajmiemy się warstwą prezentacyjną ASP.NET MVC, czyli widokiem. Do czasu wydania trzeciej wersji ASP.NET MVC sprawa była prosta. Mieliśmy jeden mechanizm odpowiedzialny za renderowanie widoku i musieliśmy się go trzymać. Wprawdzie można było napisać własny mechanizm widoku, jednak podobnie jak w Zend Frameworku mija się to z celem. Napisałem mieliśmy, ponieważ wraz z premierą ASP.NET MVC 3, ukazał się nowy silnik widoków o nazwie Razor, oferujący jeszcze więcej możliwości.

Widok ASPX

Zaczniemy od “starego” silnika, czyli ASPX, znanego z klasycznego ASP.NET. W silniku tym dane przekazujemy poprzez obiekt ViewData, posiadający typ ViewDataDictionary. Obiekt typu ViewDataDictionary można porównać do tablicy asocjacyjnej znanej z PHP. Dla zadanego klucza przypisywana jest wartość. Zobaczmy jak to działa na przykładzie. W kontrolerze przypisujemy wartość do klucza.

public ActionResult Index()
{
    ViewData["klucz"] = "wartość";
    return View();
}

A w widoku wyświetlamy jego zawartość.

<div>
    <%= ViewData["klucz"] %>
</div>

Jak widzimy “na załączonym obrazku”, wyświetlanie treści odbywa się dzięki czemuś, co przypomina short tag znany z PHP. Wraz z pojawieniem się czwartej wersji .NET, programiści otrzymali drugi short tag, zawierający zamiast znaku równości dwukropek. Różnica w działaniu obu short tagów jest zasadnicza. W pierwszym przypadku (znak równości) kod HTML zostanie zinterpretowany, a następnie wykonany. Nie muszę chyba pisać jak bardzo jest to niebezpieczne w przypadku treści dostarczanej przez użytkownika. Problem ten rozwiązuje zapis z dwukropkiem, który zamienia krytyczne znaki na encje HTML, przez co na ekranie wyświetli się tekst w takiej formie, w jakiej został przekazany do ViewData.

Opisany powyżej sposób sprawdza się doskonale w przypadku typów prostych. Niestety w przypadku modelu nie wiemy co znajduje się w ViewData. Jak już wspomniałem ViewData jest typem słownikowym, w którym klucz posiada typ string, a wartość object. Powoduje to, że w przypadku własnych typów musimy w widoku rzutować wartość do pożądanego typu. Na szczęście ViewData posiada specjalną właściwość nazwaną Model, która w połączeniu z typem widoku jest w stanie przechować właściwy typ obiektu.

Typowanie widoków

Warto w tym miejscu warto na chwilę się zatrzymać i poznać sposób w jaki dane trafiają do widoku. Każdy widok (jak wszystko w ASP.NET MVC) posiada swój typ. W najprostszym scenariuszu widok dziedziczy po prostu po klasie ViewPage, przez co wspomniana wcześniej właściwość Model jest niczym innym jak standardowym obiektem (typ object). Widok taki nazywany jest luźno typowanym (loosely typed).

W opozycji do luźno typowanego widoku stoi widok silnie typowany (strongly typed), który również dziedziczy po klasie ViewPage, przy czym klasa ta jest klasą generyczną, gdzie typem jest nasz model. W takim widoku mamy dostęp do “prawdziwej” klasy wraz z całym dobrodziejstwem inwentarza.

Trzecim sposobem jest skorzystanie z nowego typu dostępnego od .NET 4 – dynamic jako typu w generycznej klasie ViewPage. Sposób ten pozwala na dostęp do właściwości i metod modelu w czasie wykonywania (tak jak w PHP).

Korzystanie z modelu

Jeśli mamy zdefiniowaną klasę modelu, możemy przekazać ją do widoku na dwa sposoby. Pierwszy znamy już z wcześniejszego opisu – jako właściwość Model obiektu ViewData.

Załóżmy następujący model.

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

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