Zend_ProgressBar

Einführung

Zend_ProgressBar ist eine Komponente um Fortschrittsbalken in verschiedenen Umgebungen zu erstellen und zu aktualisieren. Sie besteht aus einem einzelnen Backend, welches des Fortschritt durch eines der verschiedenen Backends ausgibt. Bei jedem Update nimmt es einen absoluten Wert und optional eine Statusmeldung und ruft dann den Adapter mit einigen vorkalkulierten Werten, wie Prozentwerte und voraussichtliche Restzeit, auf.

Grundsätzliche Verwendung von Zend_Progressbar

Zend_ProgressBar ist sehr einfach in seiner Verwendung. Man erstellt einfach eine neue Instanz von Zend_Progressbar, definiert einen minimalen und einen maximalan Wert, und wählt den Adapter der die Daten ausgibt. Wenn man die Datei ausführen will, muß man etwas ähnliches wie folgt machen:

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

while (!feof($fp)) {
    // Mach was

    $progressBar->update($currentByteCount);
}

$progressBar->finish();

Im ersten Schritt, wird eine Instanz von Zend_ProgressBar erstellt, mit einem speziellen Adapter, einem minimalen Wert von 0 und einem maximalen Wert der kompletten Dateigröße. Dann wird die Datei ausgeführt und bei jeder Schleife wird der Fortschrittsbalken mit der aktuellen Byteanzahl aktualisiert. Am Ende der Schleife, wird der Status des Fortschrittsbalken auf fertig gestellt.

Man kann auch die update() Methode von Zend_ProgressBar ohne Argumente aufrufen, das die ETA einfach neu berechnet und den Adapter aktualisiert. Das ist nützlich wenn kein Update der Daten war, man aber den Fortschrittsbalken aktualisieren will.

Persistenter Fortschritt

Wenn man den Fortschrittsbalken über mehrere Aufrufe hinweg persistent haben will, kann man den Namen eines Session Namespaces als viertes Argument an den Constructor angeben. In diesem Fall wird der Fortschrittsbalken den Adapter nicht im Constructor benachrichtigen, sondern nur wenn man update() oder finish() aufruft. Auch der aktuelle Wert, der Statustext und die Startzeit für die ETA Kalkulation werden im nächsten Ablauf erneut geholt.

Standard Adapter

Zend_ProgressBar kommt mit den folgenden zwei Adaptern:

Zend_ProgressBar_Adapter_Console

Zend_ProgressBar_Adapter_Console ist ein Textbasierter Adater für Terminals. Er kann automatisch die Terminalbreite erkennen unterstützt aber auch eigene Breiten. Kann kann definieren welche Elemente mit dem Fortschrittsbalken angezeigt werden und auch deren Reihenfolge ändern. Man kann auch den Stil des Fortschrittsbalkens selbst definieren.

Automatische Breitenerkennung der Konsole

shell_exec wird benötigt damit dieses Feature auf *nix basierenden Systemen funktioniert. Auf Windows, ist die Terminalbreite immer auf 80 Zeichen begrenzt, sodas dort keine Erkennung notwendig ist.

Man kann auch die Optionen des Adapters entweder über die set* Methoden oder durch die Übergabe eines Arrays, oder einer Instanz von Zend_Config, an den Constructor mit dem Optionen als ersten Parameter. Die möglichen Optionen sind:

  • outputStream: Ein anderer Ausgabe-Stream wenn man nicht auf STDOUT streamen will. Kann jeder andere Stream wie php://stderr oder ein Pfad zu einer Datei sein.

  • width: Entweder ein Integer oder die Konstante AUTO von Zend_Console_ProgressBar.

  • elements: Entweder NULL für Standard oder ein Array mit zumindest einer der folgenden Konstanten von Zend_Console_ProgressBar als Wert:

    • ELEMENT_PERCENT: Der aktuelle Wert in Prozent.

    • ELEMENT_BAR: Die sichtbare Begrenzung welche den Prozentwert anzeigt.

    • ELEMENT_ETA: Die automatisch berechnete ETA. Das Element wird zuerst nach fünf Sekunden angezeigt, weil es während dieser Zeit nicht möglich ist korrekte Ergebnisse zu berechnen.

    • ELEMENT_TEXT: Eine optionale Statusmeldung über den aktuelle Fortschritt.

  • textWidth: Breite in Zeichen des ELEMENT_TEXT Elements. Standard ist 20.

  • charset: Zeichensatz des ELEMENT_TEXT Elements. Standardwert ist utf-8.

  • barLeftChar: Ein String der auf der linken Seite des Zeigers des Fortschrittsbalkens verwendet wird.

  • barRightChar: Ein String der auf der rechten Seite des Zeigers des Fortschrittsbalkens verwendet wird.

  • barIndicatorChar: Ein String der für den Zeiger des Fortschrittsbalkens verwendet wird. Er kann auch leer sein.

Zend_ProgressBar_Adapter_JsPush

Zend_ProgressBar_Adapter_JsPush ist ein Adapter der es erlaubt den Fortschrittsbalken in einem Browser über Javascript Push zu aktualisieren. Das bedeutet das keine zweite Verbindung benötigt wird um den Status über den aktuell laufenden Prozess zu erhalten, sondern das der Prozess selbst seinen Status direkt an den Browser schickt.

Man kann auch die Optionen des Adapters entweder über die set* Methoden oder durch die Übergabe eines Arrays, oder einer Instanz von Zend_Config, an den Constructor mit dem Optionen als ersten Parameter. Die möglichen Optionen sind:

  • updateMethodName: Die Javascript Methode die bei jeder Aktualisierung aufgerufen werden soll. Standardwert ist Zend_ProgressBar_Update.

  • finishMethodName: Die Javascript Methode die aufgerufen werden soll wenn der Beendet-Status gesetzt wurde. Der Standardwert ist NULL, was bedeutet das nichts passiert.

Die Verwendung dieses Adapters ist recht einfach. Zuerst wird ein Fortschrittsbalken im Browser erstellt, entweder mit JavaScript oder mit vorher erstelltem reinen HTML. Dann definiert man die Update Methode und optional die Finish Methode in JavaScript, die beide ein Json Objekt als einziges Argument nehmen. Das wird die Webseite mit einem lange laufenden Prozess, in einem versteckten iframe oder object Tag, aufgerufen. Wärend der Prozess läuft wird der Adapter die Update Methode bei jedem Update mit einem Json Objekt aufgerufen, das die folgenden Parameter enthält:

  • current: Der aktuelle absolute Wert

  • max: Der maximale absolute Wert

  • percent: Der berechnete Prozentwert

  • timeTaken: Die Zeit die der Prozess bis jetzt gelaufen ist

  • timeRemaining: Die erwartete Zeit bis der Prozess beendet ist

  • text: Die optionale Statusmeldung, wenn angegeben

Beispiel 647. Grundsätzliches Beispiel für den Client-seitigen Teil

Dieses Beispiel zeigt ein grundsätzliches Setup von HTML, CSS und JavaScript für den JsPush Adapter

<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 + '%';
}

Das erstellt einen einfachen Container mit einem schwarzen Rand und einem Block der den aktuellen Prozess anzeigt. Man sollte den iframe oder object nicht mit display: none; verstecken, da einige Browser wie Safari 2 den aktuellen Inhalt dann nicht laden.

Statt einen eigenen Fortschrittsbalken zu erstellen, kann es gewünscht sein einen von einer vorhandenen Bibliothek wir Dojo, jQuery usw zu verwenden. Es gibt zum Beispiel:


Intervall der Updates

Man sollte davon Abstand nehmen zuviele Updates zu senden, da jedes Update eine Mindestgröße von 1kb hat. Das ist eine Notwendigkeit für den Safari Browser um den Funktionsaufruf darzustellen und auszuführen. Der Internet Explorer hat eine ähnliche Einschränkung von 256 Bytes.

Zend_ProgressBar_Adapter_JsPull

Zend_ProgressBar_Adapter_JsPull ist das Gegenteil von jsPush, da es ein Holen für neue Updates benötigt, statt die Updates zum Browser zu schicken. Generell sollte man den Adapter mit der Persistenz Option auf Zend_ProgressBar verwenden. Bei der Benachrichtigung sendet der Adapter einen JSON String zum Browser, der exakt wie der JSON String aussieht der vom jsPush Adapter gesendet wird. Der einzige Unterschied ist, das er einen zusätzlichen Parameter finished enthält, der entweder FALSE ist, wenn update() aufgerufen wurde, oder TRUE wenn finish() aufgerufen wurde.

Die Adapteroptionen kann man entweder über die set*() Methoden oder durch die Übergabe eines Arrays oder einer Instanz von Zend_Config mit den Optionen als ersten Parameter an den Constructor setzen. Die vorhandenen Optionen sind:

  • exitAfterSend: Beendet die aktuelle Anfrage nachdem die Daten an den Browser gesendet wurden. Der Standardwert ist TRUE.