Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: zleek, dodany: 17.09.2012 11:28, tagi: php

W dniu wczorajszym została opublikowana już 5 wersja mojego ulubionego IDE dla PHP – czyli PhpStorm. Najnowsza wersja niesie kolejne usprawnienia dla codziennej pracy z kodem, są to między innymi: usprawniony silnik podpowiadania nazw zmiennych, pól klas, a przede wszystkim zwiększona prędkość działania możliwość definiowania własnych ustawień dla CodeSniffera wsparcie dla standardów kodowania Symphony2 nowy [...]

Autor wpisu: Wojciech Sznapka, dodany: 15.09.2012 21:00, tagi: php, symfony

On xlab.pl blog I’ve posted summary and my feelings after Symfony Live London conference. Click here, to read it.

Autor wpisu: zleek, dodany: 11.09.2012 10:45, tagi: php, zend_framework

W minionym tygodniu została wydana stabilna wersja Zend Framework 2. Najnowsze wydanie można pobrać klikając ten link. Nowa wersja frameworka różni się dość znacząco od wersji oznaczanych cyfrą 1. Przede wszystkim wiele komponentów zostało napisanych od nowa znacznie ułatwiając ich implementację, a także usprawniając ich prędkość działania i stabliność. Co jednak wydaje się być najciekawszą [...]

Autor wpisu: Marek, dodany: 10.09.2012 09:15, tagi: php, zend_framework

zf2

Po ponad pięciu latach od wydania wersji 1.0.0 Zend Framework doczekał się stabilnej wersji 2.0.0.

Nie będę ględził, tylko odsyłam na odświeżoną stronę: http://framework.zend.com/ i do manuala: http://framework.zend.com/manual/2.0/en/index.html

Autor wpisu: Śpiechu, dodany: 09.09.2012 22:15, tagi: mysql

Ponieważ dawno nie pisałem o bazach danych, dzisiaj coś dla miłośników wyzwalaczy i procedur składowanych w MySQL. Ile razy myśleliście, że fajnie by było żeby coś „samo się robiło”? Taką samosię można napisać dosyć łatwo jeśli chcemy stworzyć mechanizm śledzenia historii rekordu. Wpis rozbiję na dwie części z uwagi na to, że w następnej skomplikuję całość o tworzenie historii rekordu z wielu tabel.

Załóżmy, że mamy tabelę Ogloszenie, w której trzymamy dane, które chcemy śledzić. Ma następującą strukturę:

CREATE TABLE IF NOT EXISTS `Ogloszenie` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `modified_by` INT(11) NOT NULL,
  `data` TEXT NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Tabela śledząca ogłoszenie będzie wyglądała mniej więcej tak (nie śmiać mi się z polsko-angielskich hybryd nazewniczych):

CREATE TABLE IF NOT EXISTS `OgloszenieHistory` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `ogloszenie_id` INT(11) NOT NULL,
  `change_type` enum('created','modified','deleted') NOT NULL,
  `user_id` INT(11) NOT NULL,
  `event_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `data` TEXT NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Wiemy, że możemy podczepiać się pod zmiany w bazie danych za pomocą wyzwalaczy (triggerów). Tworząc historię wystarczy śledzić zmiany w postaci zapytań typu insert, update i delete. Wyzwalacze będą różnić się właściwie tylko typem wykonanego zapytania. Nie wiem jak wam, ale mnie na kilometr „zajechało” redundancją kodu wyzwalaczy, więc napiszemy sobie procedurę składowaną, którą każdy z wyzwalaczy będzie odpalał. Jest to najtrudniejsze zadanie (kod procedur wykrzacza się jak szalony).

DELIMITER $$
CREATE PROCEDURE `ogloszenie_history`(IN `id` INT, IN `change_type` ENUM('created','modified','deleted')) 
MODIFIES SQL DATA 
BEGIN 
  DECLARE p_user_id INT; 
  DECLARE p_data TEXT; 
 
  # Wyciagam dane ze zmienianego wiersza i wrzucam do zadeklarowanych wczesniej zmiennych.
  SELECT modified_by, DATA INTO p_user_id, p_data FROM Ogloszenie WHERE id=id LIMIT 1;
 
  # Wrzucam wiersz do historii.
  INSERT INTO OgloszenieHistory (ogloszenie_id, change_type, user_id, DATA) 
    VALUES (id, change_type, p_user_id, p_data);
 
END$$
DELIMITER ;

Zwróćcie uwagę na pole change_type, którego dopuszczalne wartości to created, modified i deleted, czyli dokładnie takie jak w tabeli OgloszenieHistory. Skutecznie zawęzi nam to możliwość „zatrucia” historii niezrozumiałymi typami zmian. Pozostało zrobienie wyzwalaczy:

DROP TRIGGER IF EXISTS `inserted_ogloszenie`;
DELIMITER //
CREATE TRIGGER `inserted_ogloszenie` AFTER INSERT ON `Ogloszenie`
 FOR EACH ROW BEGIN
  # Podpinamy sie po insercie dysponujac swiezo auto inkrementowanym ID wiersza.
  CALL ogloszenie_history(NEW.id, 'created');
END//
DELIMITER ;
DROP TRIGGER IF EXISTS `updated_ogloszenie`;
DELIMITER //
CREATE TRIGGER `updated_ogloszenie` AFTER UPDATE ON `Ogloszenie`
 FOR EACH ROW BEGIN
  # Podajemy id zmienionego rekordu.
  CALL ogloszenie_history(NEW.id, 'modified');
END//
DELIMITER ;
DROP TRIGGER IF EXISTS `deleted_ogloszenie`;
DELIMITER //
CREATE TRIGGER `deleted_ogloszenie` BEFORE DELETE ON `Ogloszenie`
 FOR EACH ROW BEGIN
  # Zanim baza skasuje wiersz zapiszemy sobie TO wydarzenie.
  CALL ogloszenie_history(OLD.id, 'deleted');
END//
DELIMITER ;

Śledzenie historii przedstawione powyżej jest o tyle dobre, że zwalnia nas z pisania jakiegokolwiek kodu po stronie aplikacji. Wszystko robi za nas baza. Dodatkowo mamy pełny wgląd kto i kiedy zmieniał dane. Przykładowe wpisy w tabeli OgloszenieHistory:

id, ogloszenie_id, change_type, user_id, event_date,           data
1   1              'created'    1        '2012-09-05 18:09:03' 'First data'
2   1              'modified'   2        '2012-09-05 18:09:16' 'Modified data'
3   1              'modified'   1        '2012-09-05 18:09:29' 'Modified data drugi raz'
4   2              'created'    1        '2012-09-05 18:09:37' 'Second data'
5   1              'deleted'    2        '2012-09-05 18:42:42' 'Modified data drugi raz'

W zastosowaniach praktycznych nie mamy właściwie do czynienia z bazami bez relacji, więc taka prosta historia na niewiele się zda. W następnej części wprowadzę śledzenie relacji typu wiele-do-wielu. Kiedy będzie następna część? Wtedy kiedy będzie mi się chciało pisać ;-)

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: bastard13, dodany: 07.09.2012 16:14, tagi: oop

a na co mnie to?

Testy jednostkowe (jak i wszelkie pozostałe) przydają się. Co prawda nie są, jak sądzą niektórzy, gwarancją tego, że nasz kod nie posiada błędów i jest wolny od jakichkolwiek pomyłek. Dają nam jedynie informacje, że nie udało się danego błędu znaleźć oraz, co równie ważne, że w określonych przypadkach kod/aplikacja zachowuje się tak, jak zakładamy.Ta druga informacja jest w stanie ułatwić nam życie w naprawdę wielkim stopniu, gdy dochodzimy do momentu, gdy kod trzeba refaktoryzować/modyfikować. Testy dają nam pewność, że w danych przypadkach, po wszystkich wprowadzonych zmianach, wszystko nadal działa w sposób prawidłowy. Czytaj więcej »
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.