Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Tomasz Kowalczyk, dodany: 12.07.2011 22:50, tagi: apache

Od dłuższego czasu jestem bardzo zadowolonym użytkownikiem systemu zarządzania projektami Redmine. Pomimo tego, że jest on napisany w Ruby, używa się go bardzo wygodnie, w miarę bezproblemowo można go także skonfigurować według własnych wymagań. Jednym z problemów jest jednak dosyć niestandardowe rozmieszczenie linków do niektórych funkcji systemu, przez co o niektórych możliwościach nie wiemy lub [...]

Autor wpisu: sokzzuka, dodany: 12.07.2011 09:54, tagi: php

Ostatnio w pracy miałem za zadanie zrobić upload plików w module zarządzania plikami w firmowym CMS-ie. Jak pewnie się domyślacie, oprócz uploadu samego pliku, należy wpisać jakieś informacje o nim do bazy danych, cały proces jest generalnie dość oczywisty nawet dla początkującego. Jeżeli chcemy zachować spójność operacji – czyli mieć pewność, że nie wpiszemy niczego do bazy jeżeli plik nie został poprawnie wrzucony lub na odwrót, że w razie błędu połączenia z bazą danych plik zostanie usunięty z dysku możemy wybrać dwie drogi postępowania:

  • instrukcje warunkowe (zwane popularnie „ifami” ;p )
  • transakcje

Druga  metoda zwykle sprowadza się do bloku „try-catch” oraz transakcji na bazie danych. Ja natomiast dzisiaj chciałbym zaprezentować podejście alternatywne oparte na wzorcu o wdzięcznie przetłumaczonej na polski nazwie „Polecenie” (Command).

Wzorzec „Command” polega na enkapsulacji całej logiki potrzebnej do wykonania jakiejś czynności. Jeżeli cała logika została zaenkapsulowana, to mamy też wszelkie informację by taką operację cofnąć. Poniżej przedstawię implementację.

Implementacja składa się z kilku podstawowych elementów:

Interfejs IExecutable wskazuje na zdolność klasy do bycia wykonanym:

interface IExecutable {

    /**
     * @return boolean
     */
    public function execute();
}

Interfejs IUndoable wskazuje na zdolność klasy do cofnięcia operacji:

interface IUndoable {

    /**
     * @return void
     */
    public function undo();
}

Całość zostaje złożona w abstrakcyjny typ ACommand:

abstract class ACommand implements IUndoable, IExecutable {

}

Kolejno implementacja konkretnych operacji – przyjęcia pliku, oraz aktualizacji bazy danych. Upload:

class UploadHandler extends ACommand {

    private $_field;
    private $_destination;
    private $_targetPath;

    public function __construct($field, $destination) {
        $this->_field = $field;
        $this->_destination = $destination;
    }

    public function execute() {
        $filename = $_FILES[$this->_field]['tmp_name'];
        $targetPath = $this->_destination . $_FILES[$this->_field]['name'];
        $result = move_uploaded_file($filename, $targetPath);
        $this->_targetPath = $targetPath;
        return $result;
    }

    public function undo() {
        if (file_exists($this->_targetPath)) {
            unlink($this->_targetPath);
        }
    }

}

Aktualizacja bazy:

class DbUpdater extends ACommand {

    private $_db;
    private $_table;
    private $_data;
    private $_where;
    private $_savePoint;

    public function __construct(Zend_Db_Adapter_Abstract $db, $table, array $data, $where) {
        $this->_db = $db;
        $this->_table = $table;
        $this->_data = $data;
        $this->_where = $where;
    }

    public function execute() {
        try {
            $query = $this->_db->select();
            $query->from($this->_table);
            $query->where($this->_where);
            $this->_savePoint = $this->_db->fetchRow($query);

            $this->_db->update($this->_table, $this->_data, $this->_where);
            return true;
        } catch (Exception $e) {
            return false;
        }
    }

    public function undo() {
        if (!empty($this->_savePoint)) {
            $this->_db->update($this->_table, $this->_savePoint, $this->_where);
        }
    }

}

By ułatwić korzystanie z undo, stworzyłem jeszcze jedną klasę, reprezentującą transakcje:

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

Autor wpisu: batman, dodany: 12.07.2011 08:00, tagi: css

Dzięki popularyzacji nowoczesnych przeglądarek, mamy możliwość rezygnacji ze stosowania plików graficznych i w ich miejscu wykorzystywania czystego CSS. Jednym z elementów strony, który można w całości wykonać przy pomocy CSS, jest przycisk.

Od strony HTML kod jest banalny.

<a href="#" class="button">Kliknij mnie</a>

CSS również nie jest zbyt skomplikowany.

.button {
    background-color: #efefef;
    border: 1px solid #bbbbbb;
    -moz-border-radius: 7px;
    -webkit-border-radius: 7px;
    border-radius: 7px;
    -moz-box-shadow: 2px 2px 3px #cccccc;
    -webkit-box-shadow: 2px 2px 3px #cccccc;
    box-shadow: 2px 2px 3px #cccccc;
    text-decoration: none;
    color: #3d3d3d;
    font-family: Calibri, Verdana, Arial, sans-serif;
    font-size: 18px;
    outline: none;
    padding: 3px 10px;
}

.button:active {
    -moz-box-shadow: 2px 2px 3px #cccccc inset;
    -webkit-box-shadow: 2px 2px 3px #cccccc inset;
    box-shadow: 2px 2px 3px #cccccc inset;
}

I już. W efekcie uzyskamy dwustanowy przycisk działający we wszystkich nowoczesnych przeglądarkach (również w IE9), który wygląda następująco.

buttons

Prawda, że proste?

Autor wpisu: sokzzuka, dodany: 11.07.2011 11:39, tagi: php

Pewnie niektórzy stali czytelnicy mojego bloga pamiętają, że jakiś czas temu rozpocząłem cykl o Domain Driven Design. Zaczął się on od prostego wprowadzenia, po którym coraz to bardziej zagłębiałem się w temat od strony teoretycznej, by w pewnym momencie zaanonsować, że niedługo umieszczę przykładową aplikację w PHP napisaną przy pomocy tej metodyki. Ostatni artykuł z tego cyklu umieściłem 12 listopada 2010… (tu zapada niezręczna cisza). Jako, że od tego czasu blog cały czas żył, mogło by się wydawać, że zaniedbuje moich drogich czytelników zainteresowanych tym tematem. Nic bardziej błędnego ! Prawda jest taka, że przez cały czas zgłębiałem swą wiedzę oraz implementowałem konkretną aplikację w metodyce DDD.

Aplikacja, którą tworzyłem, była w istocie tą samą, którą chciałem stworzyć w ramach zapowiedzianego  przykładu DDD. Co więcej, jako, że było to już moje drugie podejście do tematu (aplikację w tej samej domenie tradycyjnymi metodami już raz stworzyłem), miałem okazję przyjrzeć się oraz przekonać jakie różnice są między obiema podejściami oraz poznać ich wady i zalety.

Pewnie za jakiś czas zaprezentuje wyniki mojej pracy na forum publicznym, natomiast jak na razie, chciałbym wymienić benefity, których już doświadczyłem, ze względu na zastosowanie DDD:

  • łatwość w modyfikacji
  • łatwość w znajdywaniu i usuwaniu błędów

Powyższe efekty wynikają bezpośrednio z takich cech oprogramowania pisanego w metodyce DDD jak:

  • skupienie się na metodach biznesowych
  • maksymalna enkapsulacja
  • terminy ze słownika domeny użyte w kodzie
  • przejrzysty przepływ sterowania
  • pełna testowalność

Więcej szczegółów ujawni się z pewnością samo, przy okazji oglądania kodu owej aplikacji, gdy już ją opublikuje. Tymczasem zachęcam wszystkich do przeczytania swoistego wstępu do DDD, który ostatnio pojawił się w czasopiśmie Software Developers Journal, gdzie Sławomir Sobótka – znany ekspert w dziedzinie DDD dzieli się swoją wiedzą wraz ze zrozumiałymi przykładami w Javie / C#. Czasopismo oczywiście można pobrać za darmo w formie PDF-a.

Autor wpisu: batman, dodany: 11.07.2011 08:00, tagi: javascript

Podczas niedanej premiery Platform Preview IE10 oznaczonej numerem drugim, dowiedzieliśmy się, że Internet Explorer 10 dołączył do grona przeglądarek obsługujących Web Workers. W ten oto sposób, wszystkie najważniejsze desktopowe przeglądarki wspierają tę technologię. Niestety w przypadku mobilnych przeglądarek tylko Opera Mobile umożliwia korzystanie z Web Workers.

Czy w ogóle są Web Workres? Jest to technologia pozwalająca wykonywać skrypty JavaScript w tle, równolegle do głównego wątku, dzięki czemu długo działające skrypty nie blokują interfejsu użytkownika. W dużym uproszczeniu można je porównać do popularnego Ajaxa.

Zasada działania Web Workers jest banalna i sprowadza się do utworzenia obiektu Worker oraz odebrania/wysłania wiadomości do i z skryptu uruchomionego w tle. Warto już na początku wiedzieć, że skrypt uruchomiony w tle nie ma możliwości operować na drzewie DOM. Dlatego wszystkie informacje o konieczności modyfikacji drzewa DOM należy wysłać do głównego skryptu.

Zacznijmy od utworzenia workera.

var worker = new Worker("pracus.js");

Teraz musimy dodać handlera, który będzie reagował na widomości wysyłane przez workera.

worker.onmessage = function(event) {
};

Warto również zdefiniować hadlera przechwytującego błędy.

worker.onerror = function(event) {
};

Jeśli jako workera wskażecie istniejący, ale pusty plik, wówczas zgłoszony zostanie błąd. Dlatego zawsze dodawajcie do pliku workera pustą linię.

Dane odbierane ze skryptu działającego w tle zostały umieszczone we właściwości data. Z kolei informacje o błędzie znajdują się we właściwościach message (treść błędu), filename (nazwa pliku, w którym wystąpił błąd) oraz lineno (wiersz, w którym wystąpił błąd).

Wysłanie wiadomości do workera pracującego w tle odbywa się przy pomocy metody postMessage, wywołanej na obiekcie workera. Wiadomością może być dowolny ciąg, JSON lub dowolny obiekt, który można zserializować. Jedyne czego nie możemy przesłać, to obiekty zawierające metody.

worker.postMessage({
    id: 123,
    user: "jankowalski"
});

Po zebraniu wszystkiego w jedną całość, uzyskujemy taki oto skrypt.

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

Autor wpisu: Tomasz Kowalczyk, dodany: 10.07.2011 12:29, tagi: framework, php, symfony, symfony2

Pomimo raczej niezbyt odległej w czasie premiery stabilnej wersji Symfony2 wiele istniejących aplikacji zostało napisanych w pierwszej wersji tego frameworka i niestety przeniesienie ich na "dwójkę" nie jest możliwe z wielu powodów. W związku z tym, że pomimo tego, że ekscytujemy się nowymi możliwościami w kodzie, nadal musimy utrzymywać te starsze, dzisiejszy Linkdump chciałbym poświęcić [...]

Autor wpisu: sokzzuka, dodany: 09.07.2011 15:56, tagi: php

Witam, z racji, że wprowadzono nowy tryb rozwijania PHP, od teraz każdy nowy feature w momencie kiedy jest gotowy, ląduje pod głosowanie, w którym prawo mają brać udział osoby mające konto na wiki.php.net. Najnowsze głosowanie odbywa się nad nowościami, które mają się znaleźć w PHP 5.4.  Jego aktualne wyniki możecie znaleźć stronie https://wiki.php.net/todo/php54/vote ,w każdym głosowaniu można również zobaczyć, kto i jak głosował.

Jedną z informacji, która pewnie wielu ucieszy, jest to, że prawdopodobnie przejdzie krótki zapis tablic w postaci:

$someArray = ['jeden' => 1, 'dwa' => 2, 'trzy' => 3];

ostateczną śmierć poniosą również ukochane przez wielu magic_quotes.

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