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.
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.
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.
Zend_ProgressBar
kommt mit den folgenden zwei Adaptern:
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 wiephp://stderr
oder ein Pfad zu einer Datei sein. -
width
: Entweder ein Integer oder die KonstanteAUTO
vonZend_Console_ProgressBar
. -
elements
: EntwederNULL
für Standard oder ein Array mit zumindest einer der folgenden Konstanten vonZend_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 desELEMENT_TEXT
Elements. Standard ist 20. -
charset
: Zeichensatz desELEMENT_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
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 istZend_ProgressBar_Update
. -
finishMethodName
: Die Javascript Methode die aufgerufen werden soll wenn der Beendet-Status gesetzt wurde. Der Standardwert istNULL
, 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 Wertmax
: Der maximale absolute Wertpercent
: 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
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
.