Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: batman, dodany: 23.11.2010 09:07, tagi: css

Przeglądając nieprzebrane zasoby Internetu, można czasem natrafić na prawdziwą perłę. Taką właśnie perłą jest zestaw ikon, które powstały tylko i wyłącznie przy pomocy CSS. Co ciekawe, kod HTML jest niezwykle prosty, a cała sztuczka polega na wykorzystaniu pseudoelementów. Całość prezentuje się imponująco.

pure-css-gui-icons

Niestety muszę ostudzić wasz zapał. O ile wszystkie normalne przeglądarki (Firefox 3.5+, Safari 5+, Chrome 5+, Opera 10.6+) poprawnie wyświetlają powyższe ikonki, tak IE (nawet w wersji 9) sobie z nimi nie radzi.

Zachęcam do obejrzenia dema oraz odwiedzenia bloga autora, gdzie znajdziecie przykładowy kod.

Autor wpisu: batman, dodany: 22.11.2010 18:37, tagi: php

Mimo, iż z zawodu jestem programistą PHP, nie śledzę na bieżąco informacji związanych z planowanymi zmianami w tym języku. Najczęściej dowiadywałem się o nich w momencie wydania pierwszej stabilnej wersji. Związane było to głównie z brakiem czasu i ochoty na przegrzebywanie list dyskusyjnych oraz z przeświadczeniem, iż nie ważne co wymyślą w wersji alfa i tak się ona nie ukaże (PHP6 już od dawna wisiało w repozytorium) lub zmiany w stabilnej wersji będą tak dalekie od pierwszej propozycji, że trzeba będzie je poznawać od nowa. Na szczęście znalazł się “szaleniec”, któremu niestraszne są pehapowe listy dyskusyjne i zaczął na swoim blogu publikować najciekawsze informacje ze wspomnianych list. Wojtek Soczyński, bo o nim mowa, popełnił na początku miesiąca wpis zatytułowany Nowości z php.internals – double colon i 5.4 alpha. Pomijając cześć o T_PAAMAYIM_NEKUDOTAYIM, można się z niego dowiedzieć, że chłopaki od PHP szykują nam PHP 5.4, które będzie zawierać wszystko to, co obiecał nam PHP 6, a nawet więcej.

Początkowo chciałem przeczekać cały ten szum, związany z PHP 5.4 – przecież nie wiadomo czy, a jeśli tak, to kiedy będzie wydany. Nie było mi to jednak dane. Od kilku dni jestem bombardowany z każdej strony informacjami o czymś, co będzie zakałą każdego programisty (nie klepacza) – traits. Angielskojęzyczna blogosfera oszalała na punkcie tej funkcjonalności. Średnio co 5 minut pojawia się na Twitterze nowa wiadomość na ten temat.

If you can't beat them, join them” głosi stara maksyma i postanowiłem postąpić zgodnie z jej zaleceniem. Przejrzałem jeszcze raz na blogu Wojtka wpisy poświęcone wprowadzanym zmianom oraz zajrzałem do SVN-a (http://svn.php.net/viewvc/php/php-src/trunk/NEWS?view=markup). I co się okazało? Że traits wcale nie są najciekawszą zmianą wprowadzaną do PHP. W mojej opinii the best of PHP 5.4 to:

  1. Type hint dla typów prostych, czyli:
    class Foo
    {
    	public function bar(int $i)
    	{
    		// some stuff
    	}
    }
    Potrzebna i długo przeze mnie wyczekiwana funkcjonalność pozwalająca na znaczne zredukowanie ilości zbędnego kodu. Obawiam się jedynie o sposób w jaki PHP będzie informował o niepoprawnym typie danych. Oby był to wyjątek.
  2. Możliwość korzystania z $this w closure. Każdy kto korzystał z anonimowych funkcji w zasięgu obiektu, doceni tą drobną, acz niezbędną poprawkę.
  3. Dostęp do tablicy z poziomu funkcji/metody. Od dawna przeklinałem PHP za brak tej funkcjonalności. W końcu będzie można dostać się do tablicy bezpośrednio z funkcji, np:
    echo foo()[2];
  4. Traits. Ta funkcjonalność jest bardzo potrzeba, jednak spowoduje ogromny burdel w projektach i stanie się przykładem antywzorca tak, jak kiedyś stało się to z “obiektem matką”. Kiedyś, aby uzyskać możliwość korzystania z super-niezbędnych-metod, tworzyło się główny obiekt, po którym dziedziczyły wszystkie klasy w projekcie. Dzięki traits będzie można stworzyć “obiekt rój”, czyli dziesiątki (jeśli nie setki) klas, pakowanych do czegoś, co kiedyś było “matką”. Odnalezienie się w gąszczu zależności będzie graniczyło z cudem. Oczywiście poprawnie wykorzystane, będą dawały potężne możliwości, których czasem brakowało. Funkcjonalność ta wprowadza coś, co można porównać do metod rozszerzeń (w sporym uproszczeniu) znanych z C#.

Nie są to jedyne zmiany jakie przyniesie PHP 5.4, jednak na tych najbardziej mi zależy i na nich w pierwszej kolejności się skupię po wydaniu stabilnej wersji 5.4. Nie pozostaje nic innego jak uzbroić się cierpliwość.

Autor wpisu: Damian Rusinek, Piotr Wierzgała, dodany: 22.11.2010 18:07, tagi: php

Description:

This errors occurs when you keep your dates in unix timestamp format (represented as number of seconds from 1970/01/01). When we want to change a date to the next day, we can simply add as many second as there are in one day, which is 24 * 60 * 60 = 86400 seconds.

However when we try to do this for date: 2010-10-31, it is not working.

$time = strtotime('2010-10-31'); echo date("Y-m-d", $time) . "\n"; // 2010-10-31 $time += 86400; echo date("Y-m-d", $time) . "\n"; // still 2010-10-31

Solution:

Stop adding seconds to dates represented by unix timestamp. Instead, use:

$time = strtotime('2010-10-31'); echo date("Y-m-d", $time) . "\n"; // 2010-10-31 $time = strtotime('+1 day', $time); echo date("Y-m-d", $time) . "\n"; // 2010-11-01

Autor wpisu: Athlan, dodany: 22.11.2010 13:00, tagi: mysql, internet

Odzwyczajony od blogowania, zaabsorbowany przez niekorzystnego dla planet i blogosfery stanu rzeczy Social Media, postanowiłem wrzucić kolejny wpis, w podzięce za porady uzyskane z blogów kolegów z branży. Ostatnio moim zadaniem było zaprojektowanie struktury tabel bazy danych, która wraz z drzewem z zagłębieniem kategorii, ma przechowywać dane na temat cen za ogłoszenia publikowane w tych kategoriach.

Założenia wstępne wyglądały następująco:

  1. Każda kategoria może mieć rodzica, ale nie musi. Jak komu wygodnie, postanowiłem wybrać rozwiązanie z polem category_parent int(11) UNSIGNED, domyślnie NULL (bez rodzica).
  2. Kategorie mogą mieć ustaloną cenę za opublikowanie ogłoszenia, ale nie muszą. Dodałem pole category_data_price float(6,2) UNSIGNED, domyślnie NULL (niezdefiniowana).
  3. Kategorie, które nie mają zdefiniowanej ceny, a mają rodzica, przejmują cenę rodzica w zagłębieniu do nieskończoności. W przypadku, kiedy cena jest niezdefiniowana również dla rodziców, cena stanowi NULL.

Potrzebne mi było zapytanie, które zwróci mi zwyczajnie listę wszystkich kategorii wraz z cenami, uwzględniając zagłębienia, w jakich dana kategoria się znajduje. Podejścia składowania cen są dwa:

  1. Można zapisywać tylko cenę kategorii, która jest dla niej zdefiniowana, a przy wyciąganiu danych rekurencyjnie sprawdzać procedurą/funkcją cenę rodzica, jeżeli jest niezdefiniowana. I tak w kółko do przypadku, gdy któraś z kategorii będzie już miała zdefiniowaną cenę, bądź nie będzie się już gdzie zagłębić (kategoria nie ma rodzica).
  2. Można zapisać dwie ceny dodając pole dodatkowe, które przy będzie przechowywało wartość ceny, biorąc ją przy sprawdzaniu cen tylko przy zapisie rekordu do bazy danych.

Sposób drugi wydaje się być bardziej rozsądny w przypadku większej ilości zapytań podejmujących dane z bazy. Pierwszy odwrotnie – częściej wpisujemy coś do bazy. Z początku wybrałem pierwszy sposób, przy założeniu, że ceny będą generowane tylko w panelu administracyjnym, zatem zapytanie nie będzie wykonywane często. Niestety, moje myślenie jest bardziej abstrakcyjne, nastawione na elastyczność rozwiązań, w przyszłości cel istnienia bazy może się zmienić.

Tak czy siak, dla obu rozwiązań, trzeba stworzyć procedurę sprawdzającą ceny po rodzicach. Wygląda mniej więcej tak:

CREATE FUNCTION AnnouncementsCategoriesGetPrice(iCategoryId int(11)) RETURNS float(6,2)
BEGIN
DECLARE iResult FLOAT(6,2);
DECLARE iPointer INT(11);
 
SET iPointer = iCategoryId;
SET iResult  = (SELECT category_data_price FROM cms_announcements_categories WHERE category_id = iPointer);
 
WHILE (iResult IS NULL AND iPointer IS NOT NULL) DO
SET iResult  = (SELECT category_data_price FROM cms_announcements_categories WHERE category_id = iPointer);
SET iPointer = (SELECT category_parent FROM cms_announcements_categories WHERE category_id = iPointer);
END WHILE;
 
RETURN iResult;
END

Stosować ją można dla SELECT’u kategorii lub do pozyskania wartości pola tymczasowego przy zapisie do bazy.

Mam nadzieję, że komuś się przyda.

Autor wpisu: matipl, dodany: 22.11.2010 11:56, tagi: php, internet

SDJ Extra 1/201010 listopada proponowałem Wam swoją listą magazynów dostępnych w formacie PDF. Dzisiaj natomiast przychodzi mi wspomnieć o wydaniu Extra magazynu Software Developer’s Journal.

W nowym numerze poświęconym hostingowi (SDJ Extra 1/2010) znajdziecie artykuł mojego autorstwa. Zebrałem w nim wiedzą na temat postawienia lekkiego serwera WWW z PHP na VPS’ie. Dowiecie się jak skompilować nginx (serwer WWW) wraz z php-fpm 5.3.3. Do tego jest wzmianka dlaczego warto korzystać z  APC i memcached.

Taką konfigurację polecam każdemu posiadaczowi VPS‘a. Oczywiście w artykule jest zarysowana wstępna konfiguracja instalowanych usług i na pewno należy ją dostosować pod siebie (chociażby wielkość pamięci RAM przeznaczona dla APC).

Dodatkowo z SDJ Extra 1/2010 dowiecie się:

  • Jaki jest polski rynek hostingu?
  • Jakimi czynnikami kierujemy się przy wyborze hostingu?
  • Serwery VPS
  • Wprowadzenie do Amazon Simple Storage Service (S3)
  • Wykorzystanie chmury Amazon S3 za pomocą języka PHP
  • Hosting w chmurze
  • Automatyczne kopie bezpieczeństwa serwisu WWW
  • Tworzenie skryptów w technologiach typu Flash i Silverlight

Polecam.

Autor wpisu: Daniel Burchardtt, dodany: 21.11.2010 19:28, tagi: php

Twitter.comTwitter – darmowy serwis społecznościowy udostępniający usługę mikroblogowania umożliwiającą użytkownikom wysyłanie oraz odczytywanie tak zwanych tweetów. Tweet to krótka, nieprzekraczająca 140 znaków wiadomość tekstowa wyświetlana na stronie użytkownika oraz dostarczana pozostałym użytkownikom, którzy obserwują dany profil.

Informację wstępne

Serwis dostarcza nam bogate API oraz dokumentacje dzięki któremu możemy zbudować nasze aplikacje korzystające z jego możliwości.

W sieci jest dostępna masa przykładów dzięki którym możemy np. dodać tweeta do naszego konta. Przykładowy kod znaleziony w sieci

<?php
$username = 'myUserName';
$password = 'myPassword';
$status = urlencode(stripslashes(urldecode('This is a new Tweet!')));

if ($status) {
$tweetUrl = 'http://www.twitter.com/statuses/update.xml';

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "$tweetUrl");
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, "status=$status");
curl_setopt($curl, CURLOPT_USERPWD, "$username:$password");

$result = curl_exec($curl);
$resultArray = curl_getinfo($curl);

if ($resultArray['http_code'] == 200)
echo 'Tweet Posted';
else
echo 'Could not post Tweet to Twitter right now. Try again later.';

curl_close($curl);
}
?>

Niestety, wynikiem powyższego skryptu będzie zawsze komunikat o treści

Could not post Tweet to Twitter right now. Try again later.

Wszelkie możliwości dodawania tweetów w ten sposób zostały zablokowane. Jedyną możliwością jest użycie API.

API

Lista możliwości dostępnych w API jest bardzo duża, lecz zajmiemy się kilkoma podstawowymi funkcjami które dostarcza nam biblioteka ułatwiająca jego wykorzystanie. Mowa o bibliotece o nazwie Twitter for PHP stworzona przez Davida Grudl-a i udostepiona tutaj. Do jej działania wymagane jest PHP5 lub nowsze oraz biblioteka cURL.

Pierwszym krokiem jest założenie konta na Twitter.com a następnie rejestracja swojej aplikacji pod tym adresem. Należy pamiętać aby w formularzu wybrać następujące opcje

Application Type: Client

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

Autor wpisu: Piotr Śliwa, dodany: 21.11.2010 01:32, tagi: php

Testy jednostkowe, jak sama nazwa wskazuje, polegają na testowaniu jednostki - jednego obiektu w ramach jednego zestawu testów. Co jednak w sytuacji, gdy testowany obiekt jest zależny od innego obiektu? Przy bezpośrednim wykorzystaniu tego dodatkowego obiektu w testach jednostkowych jest łamana podstawowa ich zasada. Przy wykorzystaniu rzeczywistego obiektu pomocniczego, robimy ślepe założenie, że działa on prawidłowo i nie zakłóci on wyników testów. Innymi słowy testy mogą się nie powieść, ale nie oznacza to jednoznacznie, że to w testowanej klasie jest błąd. Sytuacja może się również paradoksalnie odwrócić, testy zostaną przeprowadzone prawidłowo, mimo iż testowana klasa zawiera błędy, które powinny zostać wykryte.

Jedno z rozwiązań tego problemu przedstawiłem w poprzednim wpisie na temat wzorca Service Stub. Teraz postaram się pokazać inne podejście, a mianowicie wykorzystanie obiektów Mock.

Zazwyczaj test wygląda tak, że wywołujemy operacje na obiekcie testowanym, a następnie przeprowadzamy asercje na stanie tego obiektu - nazywa się to weryfikacją stanu. Inne podejście do testowania mówi o testowaniu zachowania danego obiektu, a nie jego stanu - interesuje nas nie to, czy po wywołaniu metody prawidłowo zmienił się stan obiektu, ale to czy obiekt ten zachował się prawidłowo.

Prosty przykład oprę na chyba najprostszej z możliwych implementacji wzorca Composite:

[PHP]
  1. class Composite
  2. {
  3. private $parent;
  4. private $children = array();
  5.  
  6. private function setParent(Composite $parent)
  7. {
  8. $this->parent = $parent;
  9. }
  10.  
  11. public function addChild(Composite $child)
  12. {
  13. if ($child->getParent()) {
  14. $child->getParent()->remove($child);
  15. }
  16.  
  17. $child->setParent($this);
  18. $this->children[] = $child;
  19. }
  20.  
  21. public function remove(Composite $child)
  22. {
  23. $index = $this->findChildIndex($child);
  24.  
  25. if ($index !== null)
  26. {
  27. unset($this->children[$index]);
  28. return true;
  29. }
  30.  
  31. return false;
  32. }
  33.  
  34. public function getChildren()
  35. {
  36. return $this->children;
  37. }
  38. }

Chcemy przetestować dodawanie potomków, tak więc na początku sprawdzamy ile potomków ma testowany obiekt, dodajemy obiekt i ponownie sprawdzamy liczbę potomków:

[PHP]
  1. class CompositeTest extends PHPUnit_Framework_TestCase
  2. {
  3. private $composite;
  4.  
  5. public function setUp()
  6. {
  7. $this->composite = new Composite();
  8. }
  9.  
  10. public function testAddingChildren()
  11. {
  12. $this->assertEquals(0, count($this->composite->getChildren()));
  13.  
  14. $child = new Composite();
  15. $this->composite->addChild($child);
  16.  
  17. $this->assertEquals(1, count($this->composite->getChildren()));
  18. }
  19. }

W tym teście interesuje nas efekt, czyli to czy po dodaniu dziecka faktycznie stan testowanego obiektu się zmienił.

Przy wykorzystaniu obiektu Mock weryfikujemy to, w jaki sposób zachował się testowany obiekt. Sprawdzamy, czy wywołał on określoną liczbę razy odpowiednie metody obiektu Mock. W naszym przypadku sprawdzamy, czy metody getParent oraz setParent zostały wywołane dokładnie po jednym razie na rzecz obiektu dziecka.

[PHP]
  1. //ciach...
  2. public funciton testAddingChildrenByMockObject()
  3. {
  4. $mock = $this->getMock('Composite', array('getParent', 'setParent'));
  5. $mock->expects($this->once())//spodziewamy się wywołania dokładnie raz metody getParent, zwróci ona false
  6. ->method('getParent')
  7. ->will($this->returnValue(null));
  8. $mock->excepts($this->once())//spodziewamy się wywołania dokładnie raz metody setParent
  9. ->method('setParent');
  10.  
  11. $this->composite->addChildren($mock);
  12. }

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.