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

Autor wpisu: Łukasz Socha, dodany: 09.09.2012 21:04, tagi: php

pobierz w .pdf(przeznaczone do wydruku)

Głównym obszarem wykorzystania wzorca Obserwator jest stworzenie relacji typu jeden-do-wielu łączącej grupę obiektów. Dzięki zastosowaniu wzorca zmiana stanu (czyli zmiana aktualnych wartości pól) obiektu obserwowanego umożliwi automatyczne powiadomienie o niej wszystkich innych dołączanych elementów (obserwatorów).

Diagram klas wzorca Observer

Interfejs Subject definiuje operacje attach() i detach() pozwalające odpowiednio na dołączanie i odłączanie obserwatorów. Ponadto zdefiniowana jest też operacja notify(), służąca do powiadamiania wszystkich zarejestrowanych obserwatorów o zmianie stanu obiekt obserwowanego poprzez wywołanie w pętli metody update(), która jest zadeklarowana w interfejsie Observer. Operacja ta jest implementowana w klasie realizującej ten interfejs i służy do powiadamiania konkretnego obserwatora o zmianie stanu obiektu obserwowanego.

Przykładowa implementacja

<?php

class Observer1 implements SplObserver {

    public function update(SplSubject $subject) {
        echo 'Aktualizacja Observer1';
    }

}

class Observer2 implements SplObserver {

    public function update(SplSubject $subject) {
        echo 'Aktualizacja Observer2';
    }

}

class Subject implements SplSubject {

    protected $observers = array();

    public function attach(SplObserver $observer) {
        $this->observers[spl_object_hash($observer)] = $observer;
    }

    public function detach(SplObserver $observer) {
        unset($this->observers[spl_object_hash($observer)]);
    }

    public function notify() {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

}

$subject = new Subject();
$observer1 = new Observer1();
$observer2 = new Observer2();

$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();

?>

Przykład z życia wzięty

No i tu zaczynają się małe schody … Ze względu na specyfikę PHP (aplikacja „działa” raptem ułamki sekund) użyteczność tego wzorca jest nieco ogranicza w porównaniu z innymi językami (Java, C++ itp.). Jednak, mimo tego da się wykorzystać dobrodziejstwa Obserwatora w PHP.

<?php

class CacheObserver implements SplObserver {

    public function update(SplSubject $subject) {
        echo "Odswieza cache";
    }

}

class RSSObserver implements SplObserver {

    public function update(SplSubject $subject) {

        echo "Odswieza RSS";
    }

}

class NewsletterObserver implements SplObserver {

    public function update(SplSubject $subject) {

        echo "Wysylam maile z nowym newsem";
    }

}

class News implements SplSubject {

    private $observers = array();

    public function attach(SplObserver $observer) {
        $this->observers[spl_object_hash($observer)] = $observer;
    }

    public function detach(SplObserver $observer) {
        unset($this->observers[spl_object_hash($observer)]);
    }

    public function notify() {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

    public function add($data) {
        echo 'Dodaje news do bazy';
        $this->notify();
    }

}

$news = new News();

$news->attach(new RSSObserver());
$news->attach(new CacheObserver());
$news->attach(new NewsletterObserver());

$news->add(array(
    'title' => 'Tytuł',
    'content' => 'blablabla'
));

?>

Do obiektu klasy News, który jest obserwowany dodajemy trzech obserwatorów. Dzięki temu zabiegowi przy dodawaniu nowego artykułu elementy systemu zostaną „poinformowane” i odświeżą dane w cache/RSS oraz wyślą odpowiednie maile do czytelników.

Zalety i wady

Zalety:

  • Luźna zależność między obiektem obserwującym i obserwowanym. Ponieważ nie wiedzą one wiele o sobie nawzajem, mogą być niezależnie rozszerzane i rozbudowywane bez wpływu na drugą stronę.
  • Relacja między obiektem obserwowanym a obserwatorem tworzona jest podczas wykonywania programu i może być dynamicznie zmieniana.
  • Możliwość zablokowania klientowi drogi do bezpośredniego korzystania ze złożonego systemu, jeśli jest to konieczne.

Wady:

  • Obserwatorzy nie znają innych obserwatorów, co w pewnych sytuacjach może wywołać trudne do znalezienia skutki uboczne.

Zastosowanie

Wzorzec Obserwatora sprawdza się wszędzie tam, gdzie stan jednego obiektu uzależniony jest od stanu drugiego obiektu.

Powiązane tematy

Autor wpisu: Wojciech Sznapka, dodany: 02.09.2012 13:47, tagi: php, symfony

Everyone fall in love with Behat. It's powerfull tool for testing business requirements in PHP. Behat scenarios, written in cross-platform Gherkin language, are readable for developers, easy to understand and verify for business people and executable by machine, which goes through an application to prove that it works as expected. Behat scenarios are one of the best ways to describe system. UML Use Cases or tons of pages in SRS documents are fine, but hard to understand from the begining, and even harder to maintain in the future. Behat eases this process and also gives opportunity to automate requirements verification.

Autor wpisu: Łukasz Socha, dodany: 28.08.2012 10:35, tagi: php

pobierz w .pdf(przeznaczone do wydruku)

Ostatnio musiałem zintegrować budowany przeze mnie serwis z Facebookiem (logowanie, komentarze itp.). No i na „dzień dobry” niemiłe zaskoczenie – taki gigant jak Facebook nie ma jasnej i przejrzystej dokumentacji. Owszem są opisy metod w bibliotece i nawet przykłady aplikacji, ale opisu krok po kroku nie znalazłem…

W polskiej sieci też niewiele informacji (jak coś już znalazłem było przestarzałe). Musiałem wesprzeć się anglojęzycznymi forami. W związku z tym postanowiłem opisać integrację serwisu z FB krok po kroku w prosty i przejrzysty sposób (tak wiem, wstęp na to nie wskazuje ;) ).

No to zaczynamy

Na wstępie musimy utworzyć naszą aplikację na Facebooku. Żeby to zrobić nasze konto musi być zweryfikowane. Jak już potwierdzimy, ze my to naprawdę my ;) przechodzimy na stronę deweloperską i klikamy „utwórz aplikację”. Wyskoczy nam standardowe okienko, gdzie podajemy nazwę naszej aplikacji. Następnie przechodzimy do bardziej szczegółowej edycji.

App ID oraz App Secret będziemy musieli podać przy konfigurowaniu biblioteki, dane te nie powinny wpaść w niepowołane ręce – aplikacja nasza będzie gromadziła w końcu dane osobowe.

Spośród kilku sposobów integracji wybieramy „Website with Facebook Login” i wpisujemy adres URL do naszego skryptu, w którym przeprowadzimy logowanie z Facebookiem. Dodatkowo możemy spersonalizować naszą aplikację dodając ikonę, opis oraz określić wiek i narodowość użytkowników.

Integrowanie z naszym serwisem

Dla potrzeb stron www Facebook udostępnia JavaScript SDK oraz PHP SDK. Ja omówię wykorzystanie PHP SDK, który można pobrać stąd. Po ściągnięciu biblioteki stwórzmy plik index.php i przeprowadźmy konfigurację:

<?php
require_once 'php-sdk/src/facebook.php';

$config = array();
$config['appId'] = '412791612102295';
$config['secret'] = '4d21a055bcfef58ad427474595d5b204';

$fb = new Facebook($config);

Nasza strona jest już „połączona” z Facebookiem, pora teraz zalogować użytkownika:

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

Autor wpisu: matipl, dodany: 24.08.2012 17:57, tagi: php

php-logo

W dzisiejszych czasach niezaplątamy sobie głowy kodowaniem tworząc aplikacje w PHP. UTF-8 stał się tak popularny, że nasz zakątek świata nie potrzebuje niczego innego, a jednak…

Gorzej jeśli przyjdzie nam się zderzyć ze światem Windows i z plikami wynikowymi z tego środowiska. Oczywiście, do konwersji WINDOWS-1250 do innego kodowania możemy użyć iconv. Ale co w przypadku gdy nie wiemy skąd pochodzi plik, a w swoim nagłówku nie ma zdefiniowanego kodowania?

Taki przypadek możemy mieć w przypadku plików TXT czy CSV, których zawartość chcemy zaimportować. I wczoraj doznałem szoku. Okazuje się, że PHP nadal w pełni nie obsługuje w pełni WINDOWS-1250 – centralno europejskiego kodowania od Microsoftu. Mimo, że w tym celu powstało rozszerzenie MultiByte String wśród wspieranych kodowań brak WINDOWS-1250. W 2009 roku ten błąd był nawet zgłoszony, ale nikt się nim nie zajął.

Przewertowałem sieć i nie znalazłem funkcji, która umożliwiałaby wykrycie kodowania dla pliku, w którym możemy spodziewać się polskich znaczków, tj. UTF-8, WINDOWS-1250, ISO-8859-2. Już chciałem sobie odpuścić, ale to przecież coś bez czego tak naprawdę trudno się obyć.

Kilka minut z konsolą, i proszę – funkcja detectEncoding z obsługą WINDOWS-1250, UTF-8, ISO-8859-2.

 

function detectEncoding($string) {
  $win2utf = array(
    "\xb9" => "\xc4\x85", "\xa5" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\xc4\x86",
    "\xea" => "\xc4\x99", "\xca" => "\xc4\x98", "\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81",
    "\xf3" => "\xc3\xb3", "\xd3" => "\xc3\x93", "\x9c" => "\xc5\x9b", "\x8c" => "\xc5\x9a",
    "\x9f" => "\xc5\xba", "\xaf" => "\xc5\xbb", "\xbf" => "\xc5\xbc", "\xac" => "\xc5\xb9",
    "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83", "\x8f" => "\xc5\xb9");

    $countWin = 0;
    $found = 0;
    foreach($win2utf as $win => $utf) {
        $pos = strpos($string, $win);
        if($pos) {
            $found++;
        }

        if($pos && substr(iconv('WINDOWS-1250', 'UTF-8', $string), $pos+$countWin, 2) == $utf) {
            $countWin++;
        }
    }

    if($countWin > 0 && $found == $countWin) {
        return 'WINDOWS-1250';
    }
    if($found) {
        return 'ISO-8859-2';
    }
    return 'UTF-8';
}

I teraz możemy już konwertować pliki bez znajomości kodowania: iconv(detectEncoding($string), ‚UTF-8′, $string).

Autor wpisu: Łukasz Socha, dodany: 22.08.2012 16:56, tagi: php

pobierz w .pdf(przeznaczone do wydruku)

Fasada służy do ujednolicenia dostępu do złożonego systemu poprzez udostępnienie uproszczonego i uporządkowanego interfejsu programistycznego. Fasada zwykle implementowana jest w bardzo prosty sposób – w postaci jednej klasy powiązanej z klasami reprezentującymi system, do którego klient chce uzyskać dostęp.

Diagram klas wzorca Facade

Przykładowa implementacja

<?php 

class Element1{
    public function method() {
        echo "metoda klasy Element1";
    }
}

class Element2{
    public function method() {
        echo "metoda klasy Element2";
    }
}

class Element3{
    public function method() {
        echo "metoda klasy Element3";
    }
}

class Facade{
    private $objects = array();
    
    public function __construct() {
        $this->objects[0] = new Element1();
        $this->objects[1] = new Element2();
        $this->objects[2] = new Element3();
    }
    
    public function method1() {
        $this->objects[0]->method();
    }
    
    public function method2() {
        $this->objects[1]->method();
    }
    
    public function method3() {
        $this->objects[2]->method();
    }
    
    public function apiElement1() {
        return $this->objects[0];
    }
}

// testy
$api = new Facade();
$api->method1(); // wyswietli "metoda klasy Element1"
$api->method2(); // wyswietli "metoda klasy Element2"
$api->method3(); // wyswietli "metoda klasy Element3"
var_dump($api->apiElement1());

?>

Klasa Facade zawiera obiekty klas, które stanowią elementy systemu. Wywołując metodę (method1(), method2(), method3()) tej klasy, tak naprawdę wywołujemy metody poszczególnych obiektów składowych systemu. Metoda apiElement1() jest pewnym „rozszerzeniem” fasady, która zwraca cały obiekt klasy Elemnt1 – rozwiązanie takie zezwala w łatwy sposób udostępniać całą bibliotekę wymaganą w specyficznych sytuacjach.

Przykład z życia wzięty

Mamy za zadanie stworzyć sklep internetowy, który ma umożliwić łatwą integrację z innymi serwisami. Do realizacji tego zadania musimy stworzyć API udostępniane partnerom. Najłatwiej użyć do tego wzorca fasady.

<?php 

class User{
    public function login() {
        echo "Logowanie do systemu\n";
    }
    public function register() {
        echo "Rejestracja\n";
    }
}

class Cart{
    public function getItems() {
        echo "Zawartość koszyka\n";
    }
}

class Product{
    public function getAll() {
        echo "Lista produktów\n";
    }
    
    public function get($id) {
        echo "Produkt o ID ".$id."\n";
    }
}

class API{
    private $user;
    private $cart;
    private $product;
    
    public function __construct() {
        $this->user = new User();
        $this->cart = new Cart();
        $this->product = new Product();
    }
    
    public function login() {
        $this->user->login();
    }
    
    public function register() {
        $this->user->register();
    }
    
    public function getBuyProducts() {
        $this->cart->getItems();
    }
    
    public function getProducts() {
        $this->product->getAll();
    }
    
    public function getProduct($id) {
        $this->product->get($id);
    }
}

// testy
$client = new API();
$client->register();
$client->login();
$client->getProducts();
$client->getProduct(5);
$client->getBuyProducts();

?>

Prawda, że dużo łatwiej korzystać z API niż odwoływać się bezpośrednio do składowych systemu? ;) Nie wspominając o kwestiach bezpieczeństwa…

Zalety i wady

Zalety:

  • Zmniejszenie liczby zależności między klientem, a złożonym systemem — jeśli klient nie korzysta bezpośrednio z żadnych elementów ukrytego za fasadą systemu, całość jest łatwiejsza w konserwacji i utrzymaniu.
  • Wprowadzenie podziału aplikacji na warstwy, który ułatwia niezależny rozwój elementów klienta i złożonego systemu.
  • Możliwość zablokowania klientowi drogi do bezpośredniego korzystania ze złożonego systemu, jeśli jest to konieczne.

Wady:

  • Są jakieś? ;)

Zastosowanie

Przykładem użycia wzorca fasady może być zbudowanie API, które zezwoli zewnętrznym serwisom i aplikacjom łączyć się w prosty sposób z naszą aplikacją.

Innym praktycznym przykładem jest system bankowy. Logując się na internetowe konto mamy dostęp tylko do pojedynczych składowych całego systemu (autoryzacja, przelewy, saldo konta itp).

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

Autor wpisu: matipl, dodany: 21.08.2012 18:29, tagi: php

php-logoRaptem kilka miesięcy temu udostępniono PHP w wersji 5.4, a już w miniony czwartek został wydany kolejny zestaw poprawek w ramach tej gałęzi – już szósta paczka.

Z jednej strony to cieszy – społeczność czuwa nad jednym z popularniejszych języków, ale z drugiej strony smuci fakt, że dopiero na tym etapie łata się takie błędy jak:

  • unset($array[$float]) causes a crash
  • segfault in mysqlnd_res_meta::set_mode
  • ArrayIterator::count() from IteratorIterator instance gives Segmentation fault
  • Segfault in DateInterval class when extended
  • Extending MessageFormatter and adding property causes crash
  • segfault in php_stream_wrapper_log_error with ZTS build

Przecież są to błędy wywalające naszą aplikację. Podobne błędy (jak np. w ArrayIterator) został poprawiony w gałęzi 5.3, co znaczy że błędy były od  dawna. Jeśli ktoś z Was korzysta z PHP w wersji 5.4 lub 5.3 zaktualizujcie się jak najszybciej.

Zend Framework = „DoS”

Ale to nic w porównaniu z tym co znaleziono w Zend Framework (aktualizacje coraz mniej mnie cieszą). Zend Framework do wczoraj podatne było na ataki XXE (XML eXternal Entity) oraz XEE (XML Entity Expansion), które mogły w prosty sposób służyć do przeciążenia serwera – DoS (Denial of Service). Podatne były następujące komponenty:

  • Zend_Dom
  • Zend_Feed
  • Zend_Soap
  • Zend_XmlRpc

Jeśli z nich nie korzystaliście, nie macie czego się obawiać, ale dla własnego spokoju lepiej ściągnąć aktualną wersję Zend Framework.

Autor wpisu: Wojciech Sznapka, dodany: 16.08.2012 10:45, tagi: php, symfony, symfony2

During upcoming edition of PHPCon 2012 in Kielce I’ll give a talk “Symfony2 w chmurze” (Symfony2 in the cloud). I’ll describe advantages of cloud infrastructure purposed for web applications, some use cases of cloud deployments and things which developers need to keep in mind, to get Symfony2 application work properly in such environment. More informations [...]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.