Zend_ProgressBar

Wprowadzenie

Zend_ProgressBar to komponent służący do tworzenia i aktualizacji pasków postępu (progressbar) w różnych środowiskach. Składa się na niego pojedynczy element backendu, który sygnalizuje postęp poprzez jeden z wielu dostępnych adapterów. Podczas każdej aktualizacji brana jest wartość absolutna i opcjonalna wiadomość o stanie postępu a następnie skonfigurowany adapter jest wywoływany z obliczonymi danymi takimi jak procent postępu oraz czas, jaki został do końca wykonywanej akcji.

Podstawowe użycie Zend_Progressbar

Zend_ProgressBar jest komponentem łatwym w użyciu. Należy, po prostu, utworzyć nową instancję klasy Zend_Progressbar, definiując wartość minimalną i maksymalną oraz wybrać adapter służący prezentacji danych o postępie działań. W przypadku operacji na pliku, użycie może wyglądać następująco:

$progressBar = new Zend_ProgressBar($adapter, 0, $fileSize);

while (!feof($fp)) {
    // Wykonanie operacji

    $progressBar->update($currentByteCount);
}

$progressBar->finish();

W pierwszym kroku tworzona jest instancja Zend_ProgressBar ze zdefiniowanym adapterem, wartością minimalną: 0, oraz maksymalną równą rozmiarowi pliku. Po tym następuje seria operacji na pliku w pętli. Podczas każdej iteracji pętli, pasek postępu jest aktualizowany danymi o ilości "przerobionych" bajtów pliku.

Metodę update() klasy Zend_ProgressBar można również wywoływać bez argumentów. Powoduje to przeliczenie czasu do końca wykonywanej akcji i wysłanie go do adaptera. Ten sposób może być przydatny gdy nie ma konkretnych danych do wysłania adapterowi ale niezbędna jest aktualizacja paska postępu.

Postęp utrwalony (persistent progress)

Jeśli zajdzie potrzeba utrzymania paska postępu przez wiele żądań, można w tym celu podać łańcuch znaków z przestrzenią nazw sesji jako czwarty argument konstruktora. W tym przypadku pasek postępu nie uaktualni adaptera w momencie konstruowania - niezbędne będzie wywołanie metody update() lub finish(). Obecna wartość, tekst stanu postępu oraz czas rozpoczęcia działania (wymagany przy obliczaniu czasu pozostałego do końca) będą pobrane podczas następnego żądania i uruchomienia skryptu.

Standardowe adaptery

Standardowo Zend_ProgressBar ma do dyspozycji następujące adaptery:

Zend_ProgressBar_Adapter_Console

Zend_ProgressBar_Adapter_Console to adapter tekstowy przeznaczony do użytku z terminalem (konsolą, wierszem polecenia). Adapter potrafi automatycznie wykryć dostępną szerokość ale można również podać ją ręcznie. Oprócz tego można definiować elementy, jakie mają zostać pokazane oraz ich kolejność jak również sam styl wyświetlanego paska postępu.

Automatyczne rozpoznawanie szerokości konsoli

W przypadku systemów *nix niezbędny dla tej funkcjonalności jest shell_exec. Na maszynach Windows szerokość terminala jest stała (wynosi 80 znaków) więc automatyczne rozpoznawanie szerokości nie jest potrzebne.

Opcje adaptera można ustawiać za pomocą metod set* albo przez podanie tablicy asocjacyjnej lub obiektu Zend_Config w pierwszym parametrze konstruktora. Dostępne opcje to:

  • outputStream: Strumień do którego będzie kierowany wynik. Domyślnie to STDOUT. Może być dowolnym strumieniem, np.: php://stderr lub ścieżką do pliku.

  • width: Liczba całkowita lub stała AUTO klasy Zend_Console_ProgressBar.

  • elements: Przyjmuje NULL dla domyślnej konfiguracji lub tablicę zawierającą co najmniej jedną z następujących wartości:

    • ELEMENT_PERCENT: Obecna wartość wyrażona procentowo

    • ELEMENT_BAR: Pasek pokazujący wartość procentową.

    • ELEMENT_ETA: Automatycznie obliczany czas do zakończenia operacji. Ten element jest pokazywany pierwszy raz z opóźnieniem 5 sekund bo w krótszym czasie nie ma możliwości obliczenia wiarygodnych wyników.

    • ELEMENT_TEXT: Opcjonalna wiadomość stanu postępu operacji.

  • textWidth: Szerokość elementu ELEMENT_TEXT podana w znakach. Domyślnie to 20.

  • charset: Kodowanie elementu ELEMENT_TEXT. Domyślnie to utf-8.

  • barLeftChar: Łańcuch znaków używany jako lewa krawędź paska postępu.

  • barRightChar: Łańcuch znaków używany jako prawa krawędź paska postępu.

  • barIndicatorChar: Łańcuch znaków używany jako wskaźnik paska postępu. Może zostać pusty.

Zend_ProgressBar_Adapter_JsPush

Zend_ProgressBar_Adapter_JsPush to adapter pozwalający na aktualizację paska postępu w przeglądarce poprzez JavaScript Push. To oznacza, że nie jest potrzebne nowe połączenie na potrzeby przesyłu danych o postępie operacji. Proces pracujący po stronie serwera komunikuje się bezpośrednio z przeglądarką użytkownika.

Opcje adaptera można ustawiać za pomocą metod set* albo przez podanie tablicy asocjacyjnej lub obiektu Zend_Config w pierwszym parametrze konstruktora. Dostępne opcje to:

  • updateMethodName: Metoda JavaScript, która zostanie wywołana przy każdej aktualizacji paska postępu. Domyślnie jest to Zend_ProgressBar_Update.

  • finishMethodName: Metoda JavaScript, która zostanie wywołana po zakończeniu prowadzonej operacji. Domyślna wartość to NULL, co oznacza brak reakcji.

Użycie tego adaptera jest dość proste. Na początku należy utworzyć pasek postępu w przeglądarce za pomocą poleceń JavaScript lub HTML. Następnie należy zdefiniować metodę JavaScript wywoływaną przy aktualizacji oraz (opcjonalnie) po skończeniu działania. Obie powinny przyjmować pojedynczy argument - obiekt JSON. Aby otworzyć połączenie należy wywołać długo trwającą akcję w ukrytym obiekcie iframe lub object. Podczas wykonywania tego procesu przy każdej aktualizacji adapter będzie wywoływał odpowiednią metodę przekazując do niej obiekt JSON o następujących parametrach:

  • current: Obecna wartość absolutna

  • max: Maksymalna wartość absolutna

  • percent: Obliczony procent postępu

  • timeTaken: Czas trwania procesu (do obecnej chwili)

  • timeRemaining: Oszacowanie czasu pozostałego do końca

  • text: Opcjonalna wiadomość dotycząca stanu postępu

Przykład 654. Podstawowy przykład kodu po stronie klienta

Ten przykład ilustruje prosty kod HTML, CSS oraz JavaScript do użytku z adapterem JsPush

<div id="zend-progressbar-container">
    <div id="zend-progressbar-done"></div>
</div>

<iframe src="long-running-process.php" id="long-running-process"></iframe>
#long-running-process {
    position: absolute;
    left: -100px;
    top: -100px;

    width: 1px;
    height: 1px;
}

#zend-progressbar-container {
    width: 100px;
    height: 30px;

    border: 1px solid #000000;
    background-color: #ffffff;
}

#zend-progressbar-done {
    width: 0;
    height: 30px;

    background-color: #000000;
}
function Zend_ProgressBar_Update(data)
{
    document.getElementById('zend-progressbar-done').style.width = data.percent + '%';
}

Powyższy kod tworzy prosty pojemnik z czarną granicą oraz blok wskazujący zaawansowanie procesu. Należy pamiętać by nie ukrywać elementów iframe lub object poprzez display: none; ponieważ w takiej sytuacji niektóre przeglądarki jak Safari 2 w ogóle nie pobiorą tych elementów.

Zamiast własnoręcznie tworzyć pasek postępu, można skorzystać z jednej z wielu dostępnych bibliotek JavaScript, takich jak Dojo czy jQuery. Np.:


Odstęp czasowy pomiędzy aktualizacjami

Należy upewnić się, że nie jest tworzona zbyt duża ilość aktualizacji. Każda z nich powinna przesyłać dane o wielkości co najmniej 1kB. Dla przeglądarki Safari jest to niezbędny warunek do wykonania polecenia wywołania funkcji. Internet Explorer ma podobne ograniczenie - w jego przypadku jest to 256 Bajtów.

Zend_ProgressBar_Adapter_JsPull

Adapter Zend_ProgressBar_Adapter_JsPull jest przeciwieństwem jsPush. W jego przypadku niezbędne jest "wyciągnięcie" aktualizacji zamiast "wypchnięcia" z przeglądarki. Generalnie zaleca się użycie tego adaptera z opcją utrwalania postępu Zend_ProgressBar. Jego działanie polega na wysłaniu do przeglądarki łańcucha znaków (w formacie JSON), który wygląda tak jak string JSON wysyłany przez adapter jsPush. Jedyną różnicą pomiędzy nimi jest dodatkowy parametr (w stringu wysyłanym przez adapter jsPull) o nazwie finished. Zawiera on wartość FALSE kiedy uruchamiana jest metoda update() lub TRUE w przypadku wywoływania metody finish().

Opcje adaptera można ustawiać za pomocą metod set* albo przez podanie tablicy asocjacyjnej lub obiektu Zend_Config w pierwszym parametrze konstruktora. Dostępne opcje to:

  • exitAfterSend: Flaga oznaczająca czy bieżące żądanie ma zostać zakończone po wysłaniu danych do przeglądarki. Domyślnie przyjmuje wartość TRUE.