ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/papp.sdf
Revision: 1.3
Committed: Mon Feb 5 18:43:56 2001 UTC (25 years, 8 months ago) by root
Branch: MAIN
Changes since 1.2: +151 -50 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 !init OPT_STYLE="paper"
2    
3     !define DOC_NAME "PApp - Perl-Anwendungen für die Zukunft des WWW"
4     !define DOC_AUTHOR "Marc Lehmann <pcg@goof.com>"
5     !build_title
6    
7 root 1.2 H1: PApp - Wie beschreibt man ein Chamäleon?
8 root 1.1
9     PApp ist schwer zu beschreiben, da es sich nicht auf ein spezielles
10     Problem spezialisiert sondern möglichst eine offene Universallösung sein
11     will. Unter anderem ist PApp:
12    
13     - ein Embedded-Perl-Dialekt. Es gibt verschiedene Formen: Ein "literal
14     programming style", der nicht XML-konform ist sondern beliebige Daten
15     ausgeben kann und viele Möglichkeiten des Einbettens von Perl in
16     XML. Schliesslich gibt es noch den Standard-XML-Dialekt, der eine Mischung
17     aus beidem darstellt.
18    
19     - Perl-Module, die das Arbeiten in einer CGI-artigen Umgebung
20     erlauben. Die Umgebung hält sich mehr an Apache, ist jedoch unabhängig
21     davon, ob die PApp-Anwendung in einer CGI-Umgebung, unter mod_perl oder
22     unter CGI::SpeedyCGI ausgeführt wird.
23    
24     - Eine Bibliothek (aus vielen Modulen), die das Arbeiten mit HTML, XML,
25     SQL und anderen, häufig benutzten Umständlichkeiten vereinfacht.
26    
27     - Eine grosse "State-Maschine", die technisch getrennte Programmteile
28     (z.B. CGI) logisch zu {{einer}} Applikation zusammenfasst.
29    
30     - Ein XSLT-Stylesheet-Prozessor. Damit kann man Layout und Inhalt
31     voneinander trennen. Oder auch Ausgabeformat (PDF/HTML/XML etc.) vom
32     Layout. Oder vom Inhalt...
33    
34     H2: Warum PApp geschrieben wurde
35    
36     Grosse und kleine Applikationen für das WWW zu erstellen ist sehr
37     arbeitsaufwendig. Session-Variablen kennt Perl nicht, Session- und
38     Usertracking natürlich auch nicht. Es gibt sehr gute Module, die einem
39     einen Teil der Arbeit abnehmen, aber es ist immer sehr aufwendig und
40     umständlich. Dies führt zu unübersichtlichen Programmen, die noch dazu
41     auf viele Dateien aufgeteilt sind, die nicht unbedingt der inneren Logik
42     des Programmes entsprechen. Auch Sicherheitsfehler (wie das Übergeben
43     von sicherheitsrelevanten Daten über {{hidden-fields}} moder ähnliches)
44     passieren schnell, schliesslich muss man sich bei jeder Seite überlegen,
45     wie man seine Daten weiterreicht.
46    
47     Datenbankabfragen, das Einbauen des Layouts sind sehr
48     umständlich. Internationalisierung existiert praktisch nicht.
49    
50     PApp vereinfacht alle diese Probleme, indem es sie weitestgehend
51     automatisiert.
52    
53     H1: Grundlegende PApp-Features oder "Nie wieder CGI"
54    
55 root 1.2 Zunächst möchte ich einige der vielen Features von PApp vorstellen
56     (natürlich die wichtigsten ;). Wem das zu langweilig ist und erstmal
57     eine richtige PApp-Applikation sehen will, sollte zum nächsten Abschnitt
58     gehen, "Eine einfache Anwendung mit PApp".
59    
60     H2: Applikationen statt Einzelseitenverwaltungsmonstren
61 root 1.1
62     Bei CGI oder anderen Schnittstellen ist die Sicht auf die Anwendung
63     protokollbedingt seitenbasiert - jede "logische" Seite ist eine Datei
64     oder eine Fallunterscheidung innerhalb der Datei - gemeinsame Komponenten
65     müssen in Bibliotheken (oder auch nur Include-Dateien; ist im Prinzip
66     das gleiche) abgelegt werden die auf jeder Seite erneut geladen,
67     konfigurietr und eingebaut werden müssen. Perl-Programme funktionieren
68     jedoch anders, da gibt es keine Zustände, die beim anklicken wechseln,
69     sondern ein lineares Programm. Dies läßt sich zwar auch mit PApp nicht
70     verwirklichen, aber es tut sein Bestes, diese Einschränkungen wegzuheben,
71     indem es ganze Anwendungen bearbeitet: Ob mehrere Seiten in einer Datei
72     oder eine Seite auf mehrere Dateien verteilt wird ist in PApp egal.
73    
74 root 1.2 H2: development/maintainance: Aktivposten statt Bremsklötzen
75 root 1.1
76 root 1.2 H3: Entwicklungshilfe
77 root 1.1
78 root 1.2 Programme - auch solche, die mit PApp geschrieben werden - müssen erst
79     entwickelt werden. Dabei werden Fehler gemacht. Da bei PApp sehr viele
80     Komponenten zusammenwirken können die Fehler entsprechend komplex
81     sein. Eine gute Unterstützung bei der Fehlersuche ist also wichtig.
82 root 1.1
83 root 1.2 Dies fängt damit an, dass die Zeilennummern des Quelltextes auch nach
84     der Kompilierung von Perl/XML zu reinem Perl oder z.B. in ein XSLT
85     erhalten bleiben. Sollte ein Fehler auftreten, so hat man sofort Zugriff
86     auf die Qeulldateien, einen kompletten Backtrace und natürlich die
87     State-Daten. Das Exception-System von PApp ist einfach zu benutzen (C<die>
88     genügt, will man es schöner haben benutzt man C<fancydie> ;) und
89     erweiterbar.
90 root 1.1
91 root 1.2 Im Betrieb will man natürlich keine ausführlichen Fehlermeldungen,
92     komplett mit Passwort der Datenbank usf... Deshalb protokolliert PApp
93     alle Fehler in eine SQL-Datenbank zusammen mit der State-ID, so dass
94     nur die Fehlerkategorie (plus ein nettes Textfeld, in dem der Benutzer
95     zusätzliche Informationen eingeben kann). Solange die Seite nur
96     wiederholbare Aktionen enthält, kann der Entwickler den Fehler jederzeit
97     reproduzieren.
98 root 1.1
99 root 1.2 H3: Datenbanken
100 root 1.1
101 root 1.2 Wie soll man ohne auskommen? Natürlich garnicht. In Perl gibt es ein ganz
102     wunderbares System (DBI!) um mehr-oder-weniger genormt auf SQL-Datenbanken
103     zugreifen zu können. Jetzt ist "nacktes" DBI recht umständlich,
104     zumindest für mich, für den vier Aufrufe pro SQL-Befehl entschieden zu
105     viel sind. Vor allem, wenn man diese über das Programm verstreuen muss.
106 root 1.1
107 root 1.2 In PApp erledigt man die meisten Aufgaben mit der C<sql_exec>-Funktion
108     (den Rest erledigt man mit C<sql_fetch/fetchall/exists/insertid>). Der
109     folgende Aufruf ersetzt C<prepare>, C<bind_params>, C<execute> und
110     C<bind_columns>:
111 root 1.1
112     !block perl
113 root 1.2 my $st = sql_exec \my($p, $w),
114     "select purzel, wurzel from table
115     where name like ?",
116     $S{search};
117    
118     while ($st->fetch) {
119     echo "$p, $w\n";
120     }
121 root 1.1 !endblock
122    
123 root 1.2 Der besondere Clou: Die SQL-Statements werden gecached, d.h. im
124     Allgemeinen nur ein einziges mal C<prepare>d. Bei Datenbanken, die einiges
125     an Aufwand in diesem Schritt investieren (Stichwort Query-Optimizer)
126     ist das ein grosses Plus. Sogar bei Datenbanken, die dies nicht tun
127     (z.B. MySQL) steigt die Geschwindigkeit merklich. Zudem sind das
128     C<prepare> und das C<execute> in normalen Programmen getrennt voneinander
129     (die Befehle stehen weit auseinander).
130 root 1.1
131 root 1.2 Bei Datenbanken, die eine Art "insertid" unterstützen (zum Glück fast
132     alle), kann man diese nach einem C<INSERT> gleich mit abfragen:
133 root 1.1
134     !block perl
135 root 1.2 my $id = sql_insertid
136     sql_exec "insert into tiere (name) values (?)",
137     "hase";
138 root 1.1 !endblock
139    
140 root 1.2 Den Database-Handle habe ich übrigens nicht vergessen: Wenn ich
141     keinen angebe, wird ein Default-Handle benutzt. Geschickterweise wird
142     dieser von PApp selbst gesetzt, so dass man sich im Normalfall noch
143     nicht einmal um die Datenbankverbindung kümmern muss (weil diese auf
144     dem Produktionssystem meistens andere Passwörter hat als auf dem
145     Entwicklungssystem stellt man diese geschickterweise bei der Konfiguration
146     der Applikation ein).
147 root 1.1
148 root 1.2 <<admin.png>>
149 root 1.1
150 root 1.2 H2: Trennung von Quelltext und Sprache
151 root 1.1
152 root 1.2 H3: XML
153 root 1.1
154 root 1.2 XML wird in mehreren Teilen von PApp unterstützt bzw. gefordert: Der
155     Standard-Dialekt von PApp ist in XML geschrieben, d.h. um "normale"
156     PApp-Applikationen zu schreiben muss man sich XML bedienen. Die Ausgabe
157     von PApp (meistens Text) ist beliebig, sofern man keine Stylesheets
158     benutzt. Tut man das, muss die Ausgabe natürlich in XML-Syntax sein. Und
159     last-not-least gibt es ein PApp-Modul, mit dem man beliebige XML-Fragmente
160     mit eingebettetem Perl-Quelltext bearbeiten/ausführen/anzeigen kann.
161 root 1.1
162 root 1.2 Die Entscheidung, XML so zentral einzusetzen, fiel mir nicht
163     leicht: Meiner Meinung nach ist XML wunderbar dafür geeignet,
164     Daten innerhalb von Programmen zu verarbeiten und vor allem
165     auszutauschen. Toll ist, dass Menschen XML notfalls lesen und auch
166     schreiben können. Ansonsten ist doch die Mächtigkeit von SGML (oder
167     etwas anderem) vorzuziehen.
168 root 1.1
169 root 1.2 XML jedoch hat bestechende Vorteile: HTML ist eine XML-Applikation (und
170     HTML ist wichtig ;); es existiert eine breite Unterstützung für XML;
171     es gibt bestehende Standards für Stylesheets, Layout, Metadaten und
172     mehr. Schliesslich ist XML auch noch sehr schnell. Nun ja.
173 root 1.1
174 root 1.2 Das hat mich trotzdem nicht davon abgehalten, etwas oben
175     draufzusetzen: Fast alle Dokumente können in einem "Meta-Format" mit
176     eingebettetem Perl-Quelltext geschrieben werden. Die Standard-Syntax
177     dafür bedient sich vier sog. "Modus-Umschalter", die jeweils vom
178     "Verbatim" in den "Perl"-Modus bzw. zurück schalten:
179 root 1.1
180     !block verbatim
181 root 1.2 <: schalte von HTML in Perl um
182     <? wie <:, füge jedoch das Ergebnis in die Ausgabe ein
183    
184     :> schalte in den HTML-Modus
185     ?> schalte in den interpolierten HMTL-Modus
186 root 1.1 !endblock
187    
188 root 1.2 Diese Modus-Umschalter habe ich in den Beispielen schon verwendet, z.B.
189     kann man eine HTML-Seite so schreiben:
190 root 1.1
191 root 1.2 !block perl
192     <h1>Ein bisschen HTML</h1>
193     <: echo "mit eingebautem perl" :>
194     <: print "so gehts auch, ist aber unendlich wenig langsamer ;)" :>
195     <?"So gehts am schnellsten":>
196     <:for my $text (qw(Noch eine komische Methode)) {
197     ?>$text&#160;<:
198     }:>
199     !endblock
200 root 1.1
201 root 1.2 Die Modus-Umschalter verhalten sich dabei wie eine Statement-Grenze in Perl (also C<;>).
202 root 1.1
203 root 1.2 H3: I18n
204 root 1.1
205     I18n steht kurz für Internationalisierung: Das englische Wort
206     {{Internationalization}} hat 18 Buchstaben zwischen dem 'I' und dem
207     'n', und da das Wort für den Durchschnittsamerikaner viel zu lang und
208     kompliziert ist, hat man diese 18 Buchstaben einfach durch "18" ersetzt.
209    
210     In Kontext von PApp bedeutet dies, dass beinahe überall Textmeldungen
211     übersetzt werden können (wer das C<gettext>-Paket kennt, mit dem
212     üblicherweise C-Programme internationalisiert werden, wird sich fast
213     sofort Zuhause fühlen). Hier ist ein Beispiel:
214    
215     !block verbatim
216     <h1>__"Contents"</h1>
217     <:for (1..10) {:>
218     <?slink sprintf(__"Chapter %d", $i++),
219     "view_chapter", chapterid => $i:>
220     <:}:>
221     !endblock
222    
223     Wie man sieht, kann man C<__"text"> sowohl im
224     HTML/XML/wasauchimmer-Quelltext benutzen, als auch auf Perl-Ebene
225     aufrufen. Die C<__>-Funktion erledigt dabei zwei Aufgaben: Zunächst werden damit
226     Textkonstanten zum übersetzen {{markiert}}. Zur Laufzeit wird dann in der Übersetzungstabelle nachgesehen und
227     der (evt.) übersetzte String zurückgeliefert.
228    
229 root 1.3 Wenn man Daten z.B. aus einer Datenbank in eine Variable holt, darf man
230     diese natürlich {{nicht}} markieren, da sie ja nur zur Laufzeit einen
231     String {{enthält}}, selbst aber keine Textkonstante ist. In solchen
232     Fällen verwendet man C<gettext>:
233 root 1.1
234     !block perl
235     my $st = sql_exec \my($id, $name), "select id, name from table";
236    
237     while ($st->fetch) {
238     echo "<li>", gettext$name, "</li><br/>";
239     }
240     !endblock
241    
242     In welche Sprache jeweils übersetzt wird, entscheidet bei HTTP die
243     Einstellung des Browsers, wobei man zweckmässigerweise ein Menü
244     anbietet, in dem der Benutzer dies überschreiben kann:
245    
246     !block perl
247     <?slink "I want English", SURL_SET_LANG => "en":>
248     <?slink "Deutsch willich!", SURL_SET_LANG => "de":>
249     !endblock
250    
251     Auch die Spracheinstellung ist eine Preferences-Variable. Im Gegensatz
252     zum C<gettext>-Paket müssen die Quelltext nicht alle in einer Sprache
253     sein. Bei C<gettext> ist das auch weniegr ein Problem, da der Quellcode
254     eines Programms meistens in einer (natürlichen) Sprache geschrieben
255     wurde, in PApp kann man aber Seiten dynamisch einfügen oder Datenbanken
256     übersetzen. Da diese meist nicht vom selben Team geschrieben werden, ist
257     es nützlich, dort unterschiedliche Sprachen verwenden zu können.
258    
259     <<poedit1.png>>
260     <<poedit2.png>>
261    
262 root 1.2 H3: Unicode / Zeichensatzunabhängigkeit
263 root 1.1
264     Intern unterstützt PApp genau zwei Datentypen (genau wie Perl
265     selbst): {{Binärdaten}} und {{Text}}. Binärdaten verwendet man
266     üblicherweise für Bilder, Datei-Downloads und ähnliches. Diese Daten
267     werden von PApp nicht angerührt.
268    
269     Ganz anders Text: Perl arbeitet intern mit Unicode, das z.Zt. entweder in
270     ISO-8859-1 oder UTF-8 gespeichert wird. Dieser interne Zeichensatz ist
271     völlig unabhängig von der Ausgabe, d.h. der Text wird bei der Ausgabe
272     automatisch in den gewünschten Zeichensatz kodiert (das geschieht wieder
273     Browser/Benutzer/Programmabhängig wobei von den gebräuchlichen Browsern
274     nur Netscape und Lynx die entsprechenden Header liefern). Umgekehrt werden
275     Formulardaten u.ä. automatisch in Unicode gewandelt, d.h. in C<%P> steht
276     Unicode auch wenn der Browser ein Formular in ISO-2022-JP zurückgeschickt
277     hat.
278    
279     Ein JPEG-Bild kann man z.B. so ausgeben:
280    
281     !block perl
282     content_type "image/jpeg", undef;
283     $gd->jpeg(80);
284     !endblock
285    
286     Während man eine japanische Benutzerin vielleicht mit ISO-2022-JP
287     zufriedenstellen kann:
288    
289     !block perl
290     content_type "text/html", "iso-2022-jp";
291     echo __"Hoffentlich war der Übersetzer fleissig";
292     !endblock
293    
294 root 1.2 H2: Trennung von Daten und Layout/Protokoll
295 root 1.1
296 root 1.2 Sprache und Quelltext trennt PApp ja schon. Jetzt muss man noch das Layout
297     vom eigentliche Programm bzw. das Protokoll von den eigentlichen Daten
298     trennen.
299    
300     Mit XSLT-Stylesheets geht das. Und mehr: "Browser XYZ hat ein Problem? Ich
301     fix' es im Stylesheet und vergesse es dann einfach." (z.B. sollte man
302     leere HTML-Tabellenzellen für Netscape lieber mit einem C<&nbsp;>
303     füllen). "Es soll WML (oder CHTML) sein? Ich weiss zwar nicht, wozu
304     das ganze WML-Zeugs sinnvoll sein soll, aber dann mache ich halt' ein
305     Stylesheet dafür." Und eine der wichtigsten Anwendungen: "Wir brauchen
306     eine Version zum drucken. Dafür wandeln wir unser XML-Dokument in XSL" (und dann
307     nach Latex, PDF...).
308    
309     Das bedeutet, dass man - Planung natürlich vorausgesetzt - einen hohen
310     Grad an Protokollunabhängigkeit erreichen kann, ohne den Quelltext zu
311     sehr mit Layout-Entscheidungen o.ä. belasten zu müssen.
312    
313     Leider gibt es noch keine Web-Designer, die XSLT statt HTML/CSS liefern,
314     aber (meine) Vision des Webs der Zukunft sieht so aus: Der Server liefert
315     XML zusammen mit einem XSLT (vom Designer), welches XSL erzeugt. Dieses
316     wird dann angezeigt/gedruckt etc.a.. Metadaten (mit dem etwas besseren
317     Nachfolger von RDF) gestatten dann Fragen wie: "Wer hat dieses Dokument
318     geschrieben?", "Wozu dient es?" aber auch: "Wieso ist das Ding so bunt?".
319    
320     H2: Trennung von Funktionalität und Ausführungsumgebung
321    
322     Platform-Unabhängigkeit: ein toller Begriff. Was bedeutet er? Nicht
323     viel. Bei PApp bedeutet es, dass auf Unix-Abhängigkeiten möglichst
324     verzichtet wurde und sich PApp nicht an einen bestimmten Server
325     (z.B. Apache) bindet. In der Praxis kann man als Platform mod_perl
326     oder CGI verwenden und für Windoze schere ich mich einen Dreck. Aber
327     auch andere Umgebungen wie Text-Interfaces sind denkbar: Da PApp der
328     Applikation immer eine gleichbleibende Umgebung anbietet, muss man
329     lediglich ein Schnitstellenmodul schreiben.
330    
331     H2: Persistente Variablen für Sessions und User
332    
333     PApp kümmert sich automatisch um persistente Variablen. So kann man
334     automatisch Variablen erzeugen, die über eine gesamte Sitzung (die mit
335     dem Aufruf der ersten URL beginnt und dann einen Baum bildet) persistent
336     sind. Das geht so einfach, dass man spezielle Hilfsmittel braucht, um
337     nicht an jeder Stelle der Sitzung Zugriff auf beinahe alles zu besitzen.
338    
339     Persistente Variablen gibt es in verschiedenen Geschmäckern. Es gibt:
340    
341     - Session-Variablen (sogenannte {{state keys}}), die über eine gesamte
342     Sitzung erhalten bleiben. Diese werden im Hash C<%S> gespeichert. Man kann
343     beliebige Werte darin ablegen (solange C<Storable> diese serialisieren
344     kann). Meistens gescheiht dies durch Anklicken eines Links, weniger
345     häufig direkt.
346    
347     - Benutzerabhängige Variablen (die auch über Sitzungsgrenzen hinaus
348     erhalten bleiben und deshalb {{preferences items}}, Voreinstellungen,
349     heissen). Auch diese befinden sich in C<%S>, von wo sie automatisch in die
350     Benutzerdatenbank wandern bzw, von dort gelesen werden.
351 root 1.1
352 root 1.2 - Lokale Variablen ({{local keys}}) zu nur innerhalb einer Seite oder
353     einer Gruppe von Seiten Bedeutung haben. Diese befinden sich ebenfalls in
354     C<%S> und werden automatisch daraus entfernt.
355 root 1.1
356 root 1.2 - oder beliebige Kombinationen davon.
357 root 1.1
358 root 1.2 Ein Beispiel für eine Sitzungsvariable ist die Information, ob der
359     Benutzer sich schon angemeldet/eingeloggt hat oder ob er bestimmte
360     Zugriffsrechte besitzt. Eine benutzerabhängige Variable ist z.B.die
361     Sprache, die der Benutzer zuletzt ausgewählt hat (global) oder die
362     Anzahl der Tabellenzeilen, die der Benutzer gerne auf einer bestimmten
363     Seite angezeigt haben möchte. Eine lokale Variable ist z.B. ein
364     Datenbank-Objekt, das über mehrere Seiten (z.B. einer Transaktion)
365     gebraucht wird und danach seine Gültigkeit verliert.
366 root 1.1
367 root 1.2 Dadurch ergeben sich mehr Möglichkeiten, als man erwarten
368     würde: Unabhängige Komponenten (z.B. Werbebanner oder Foren) sind auf
369     normale Weise nur sehr schwer zu programmieren, da sie immer Hilfe vom
370     "Hauptprogramm" erfordern wenn es um die Parameterübergabe geht. In PApp
371     benutzt man einfach persistente Variablen.
372 root 1.1
373 root 1.2 Ein Beispiel für eine etwas ungewöhnlichere Komponente ist die
374     {{editform}}-Bibliothek. Mit ihr kann man HTML-Formulare erstellen, die
375     sich direkt an eine bestimmte Variable binden:
376 root 1.1
377 root 1.2 !block perl
378     ef_begin;
379     ef_string \$S{search};
380     ef_end;
381     !endblock
382 root 1.1
383 root 1.2 Dieses Beispiel stammt von einer Seite, die Objekte aus einer Datenabnk
384     anzeigt und sich dabei auf solche beschränkt, die ein Suchwort
385     enthalten. Das Formular bindet die State-Variable C<search> an ein
386     HTML-Textfeld. Bei der Ausgabe wird der aktuelle Wert von C<$S{search}>
387     benutzt. Ändert der Benutzer den Text und schickt das Formular ab wird
388     die Seite neu aufgebaut - mit einem anderen Wert in C<$S{search}>. Da
389     editform beliebige Perl-Referenzen akzeptiert und man in PApp auch
390     Referenzen auf Dateien, SQL-Spalten etc... erzeugen kann werden viele
391     Formulare zum Kinderspiel.
392 root 1.1
393 root 1.2 Zusätzlich zu den Sitzungsvariablen gibt es noch sogenannte
394     {{Argumente}}, die nur eine Seite lang "persistent" sind, d.h. bei einem
395     Link auf eine andere Seite übergeben werden:
396 root 1.1
397 root 1.2 !block perl
398     echo slink "Klicken Sie hier", -argument1 => "wert1", var2 => "wert2";
399 root 1.1 !endblock
400    
401 root 1.2 Wenn man diesem Link folgt, steht der "wert1" im Hash C<%A> bzw. "wert2"
402     im Hash C<%S>:
403 root 1.1
404     !block perl
405 root 1.2 printf "Das Argument argument1 ist %s, die State-Variable var2 ist %s",
406     $A{argument1}, $S{var2};
407 root 1.1 !endblock
408    
409 root 1.2 Werte, die von "Aussen" (z.B. GET-Request in CGI) kommen, stehen, um die
410     Verwirrung komplett zu machen, in C<%P>. Als Faustregel gilt: was in C<%S>
411     und C<%A> steht ist sicher (bzw. man hat es selbst dorthin gepackt), was
412     in C<%P> steht ist unsicher und muss erst gefiltert/geprüft werden.
413    
414     H2: Sicherheit
415    
416     In vielen CGI-Programmen (aber nicht nur dort) wird der Fehler
417     begangen, sensitive Daten in {{hidden}}-Feldern in einem Formular zu
418     "verstecken" oder sie in die URL zu kodieren um die Parameterübergabe zu
419     realisieren. Dies ist in PApp nicht nötig, da der persistente 'State' in
420     einer Datenbank gespeichert wird und nur der (mit 256 Bit verschlüsselte)
421     Zeiger darauf zum Client übertragen wird. Dadurch werden sensitive Daten
422     gar nicht erst zum Client übertragen, was natürlich auch Bandbreite
423     spart. Sollte der Schlüssel einmal bekannt werden kann man zwar auf
424     andere Sessions zugreifen, die Daten jedoch immer noch nicht verändern
425     (dieser Fall tritt beispielsweise auch auf, wenn ein kaputtes Proxy
426     zwischen Server und Client sitzt).
427    
428     Eine typische PApp-URL sieht übrigens so aus (Applikation "kis", Modul
429     "abteilungswahl"):
430 root 1.1
431 root 1.2 !block verbatim
432     /kis/abteilungswahl/NIlRSJNDIfP3AHfVjxLF5F
433     !endblock
434 root 1.1
435 root 1.2 Da eine "Seite" in PApp aus einem Modulbaum besteht, geht es auch
436     komplizierter:
437 root 1.1
438 root 1.2 !block verbatim
439     /admin/+admin=poedit+poedit=view--?papp=eTDgL.I-lj9O9lTO3wznTk
440     !endblock
441 root 1.1
442 root 1.2 Zusammen mit einem sicheren Transportprotokoll (z.B. SSL, wobei die
443     meisten Browser nur ungenügend oder garnicht gegenüber Attacken
444     schützen, nur so am Rande ;) schützt man sich damit gegen alle Seiten.
445     Benutzerauthentifizierung über Zertifikate ist auch im Einsatz (mit dem
446     C<ssl>-Modul von PApp).
447 root 1.1
448 root 1.2 H2: Session/User-tracking
449 root 1.1
450 root 1.2 Persistente Variablen erfordern Session-Tracking. Benutzerabhängige
451     Einstellungen (Preferences) darüber hinaus auch User-Tracking. Ersteres
452     geschieht mit einer Session-ID, die (auf verschiedene Arten) in die
453     URL-kodiert wird und die alle notwendigen Daten enthält, um die
454     gewünschte Seite komplett zu erzeugen. Darüber hinaus wird (optional)
455     ein Cookie benutzt, das aber z.Zt. nur zum Identifizieren des Benutzers
456     dient, da ich Session-Definitionen per Cookie als Unsinn erachte. Das
457     Cookie wird auch nur einmal am Tag gesetzt, so daß man auch mit der
458     Browser-Einstellung "vor Cookies warnen" arbeiten kann.
459 root 1.1
460 root 1.2 Eine Anwendung wird darüber informiert, ob eine neue Session begonnen
461     wurde oder ob sich ein bisher unbekannter Benutzer angemeldet hat, so
462     daß man Benutzereinstellungen o.ä. initialisieren kann. Dies nützt
463     PApp selbst, um sich z.B. die Sprache des Benutzers zu merken oder um das
464     User-Cookie nur einmal täglich zu setzen.
465 root 1.1
466 root 1.2 Eine "Sitzung" ist übrigens ein Baum (nicht nur in PApp), der mit dem
467     ersten "Hit" als Wurzel beginnt. Dadurch ist es unter anderem möglich,
468     die Anzahl der "Reloads" einer Seite zu bestimmen. Dies ist nützlich,
469     um potentiell gefährliche Aktionen (z.B. Löschen von Datenbanken,
470     abschicken von E-mails) nur einmal auszuführen.
471 root 1.1
472 root 1.2 H2: Benutzerverwaltung
473 root 1.1
474 root 1.2 Da PApp Benutzer (mehr oder weniger) eindeutig identifizieren muss,
475     implementiert es intern eine eigene Benutzerverwaltung inklusive einer
476     Unix-artigen Rechtevergabe (es gibt allerdings keinen Super-User im
477     Unix-Sinne). In vielen Anwendungen kann man diese gleich mitbenutzen, da
478     eine eindeutige Benutzer-ID automatisch vergeben wird.
479 root 1.1
480 root 1.2 !block verbatim
481     Sie sind wahrscheinlich Benutzer Nummer <?$userid:><br/>
482     #if auth_p
483     Und ausserdem haben sie sich authentifiziert.<br/>
484     # if access_p "admin"
485     Oh, und "admin"-Rechte besitzen Sie auch noch! Meine Güte!!<br/>
486     # endif
487     #endif
488 root 1.1 !endblock
489    
490 root 1.2 H2: Geschwindigkeit und Skalierbarkeit
491 root 1.1
492 root 1.2 Geschwindigkeit war bei der Implementierung von PApp das zweitwichtigste
493     Ziel (Korrektheit ist das wichtigste ;). Als Marke dient mir ein
494     Pentium-II 266Mhz-Rechner, auf dem auch komplexe Seiten mit mindestens 15
495     Hits/Sekunde dargestellt werden, bzw. der Vergleich mit einem ähnlichen
496     C<Apache::Registry>-Skript.
497 root 1.1
498 root 1.2 Das State-Management von PApp verschlingt pro Seite 1-3 Datenbankzugriffe,
499     die die Zeit bei weitem dominieren (andere Features wie I18n sind im
500     Prinzip kostenlos). Da komplexe Seiten im Allgemeinen wesentlich mehr und
501     kompliziertere Zugriffe enthalten bzw. man ja irgendwie seine Daten
502     speichern muss, ist dies in der Praxis selten eine Einschränkung
503     (Ausnahmen gab und gibt es immer). Andere PApp-Features (z.B. im
504     SQL-Bereich) bringen häufig sogar eine Steigerung der Geschwindigkeit.
505 root 1.1
506 root 1.2 Da ich bisher keine Seite fabrizieren konnte, die die 15 Zugriffe/s-Marke
507     unterschritten hätte, glaube ich noch etwas Spielraum für noch mehr
508     Features zu haben. Wer sich übrigens fragt, woher diese 15 Hits/s
509     kommen: 15 Hits ist die Marke, die einen wirklich grossen Server von den
510     99.99% der restlichen Welt unterscheidet. Hat man auf seinem Server 15
511     oder mehr Zugriffe pro Sekunde kann man sich meistens auch eine schnellere
512     Datenbank oder mehrere Rechner leisten: PApp skaliert problemlos auf
513     mehrere Maschinen.
514 root 1.1
515 root 1.2 H2: Ideen, Ideen: z.B. "tied forms"
516 root 1.1
517     Ich habe es schon angesprochen: Persistenz von fast allem, zusammen mit
518     den Möglichkeiten von Perl können einen schon auf Ideen bringen, z.B.
519     auf eine Bibliothek (editform), die HTML-Formularfelder an Perl-Refrenzen
520     bindet.
521    
522     Nun ist es an der Zeit, einmal eine Referenz auf eine SQL-Tabelle zu
523     erzeugen:
524    
525     !block perl
526     <:
527     my $row = new PApp::DataRef 'DB_row',
528     table => "user",
529     where => [id => $userid],
530     delay => 1,
531     autocommit => 1;
532    
533     # pre-set name
534     $row->{name} ||= "<username>";
535    
536     ef_begin;
537     :><br>__"ID:" <?ef_string \$row->{id} , 5:><:
538     :><br>__"Name:" <?ef_string \$row->{name}, 20:><:
539     ef_submit __"Update";
540     ef_end;
541     :>
542     !endblock
543    
544     Die Referenz auf die Zeile steht in C<$row> un verhält sich wie eine
545     Referenz auf einen herkömmlichen Perl-Hash. Das C<autocommit> sorgt
546     dafür, dass die geänderten Daten automatisch zurückgeschrieben werden
547     sobald das C<$row>-Objekt gelöscht wird (ausser Scope geht, C<DESTROY>ed
548     wird). Sie ist lokal (C<my>!) gespeichert, da aber die C<ef_>-Funktionen
549     die Referenz persistent speichern, wird das Objekt erst auf der nächsten
550     Seite (also nachdem die Ergebnisse hineingeschrieben wurden!) zerstört,
551     bzw. die Daten geschrieben. Etwas kompliziert, aber zum Benutzen muss man
552     die Details ja auch nicht kennen.
553    
554     Nun macht das Beispiel keine Fehlerüberprüfung, meistens das
555     schwierigste. Mit PApp kein Problem. Zuerst schalten wir das C<autocommit>
556     ab, damit die Daten nicht "aus Versehen" geschrieben werden. Ausserdem
557     übergeben wir die Referenz als Argument an die "nächste" Seite.
558    
559     !block perl
560     <:
561     my $row = $A{row}
562     || new PApp::DataRef 'DB_row',
563     table => "user",
564     where => [id => $userid],
565     delay => 1,
566     autocommit => 0;
567    
568     ef_begin -row => $row; # Daten als Argument übergeben
569     !endblock
570    
571     Nun brauchen wir ein Flag, das uns sagt, ob der Datensatz fehlerhaft ist
572     und schon können wir loslegen:
573    
574     !block perl
575     my $err = 0; # Daten fehlerhaft?
576    
577     :><br/>__"ID:" <?ef_string \$row->{id} , 5:><:
578     #if $row->{id} !~ /^(\d+)$/
579     <error>__"The ID must be an integer!"</error>
580     <:$err++:>
581     #endif
582     :><br/>__"Name:" <?ef_string \$row->{name}, 20:><:
583     #if 2 > length $row->{name}
584     <error>__"The Name must contain at least two characters!"</error>
585     <:$err++:>
586     #endif
587     ef_submit __"Update";
588     ef_end;
589     !endblock
590    
591     Die Daten schreibt man dann bei Bedarf in die Datenbank:
592    
593     !block perl
594     #if $row->dirty
595     # if $err
596     <error>__"The entered Data is invalid, please surrender or die (or correct it ;)</error>
597     # else
598     <:$row->flush:>
599     __"The record has been updated."
600     # endif
601     #endif
602     :>
603     !endblock
604    
605     H2: "Web-Widgets"
606    
607 root 1.2 Eine relativ neue "Neuerung" in PApp ist die Einführung von
608     Web-Widgets. Wie so vieles sind das keine speziellen Objekte, sondern eine
609     Art der Programmierung, die zwar schon immer möglich warm aber an die man
610     nicht sofort denkt.
611    
612     Statt einer ganzen Applikation, die "ganze Seiten" (z.B. ganze
613     HTML-Seiten) ausgibt, schreibt man eine Applikation, die nur noch
614     Teilseiten ausgibt, die man in größere Applikationenn einbaut. Dies ist
615     nicht das gleiche wie ein "include": Der Namensraum (globale Variablen,
616     state-keys, also Session-Variablen und Preferences) einer solchen
617     eingebetteten Applikation ist getrennt von der einbettenden Anwendung und
618     bildet eine Art "Unternamensraum".
619    
620     Derlei eingebettete Anwendungen sind vollkommen autark, haben ihren
621     eigenen Zustand ("aktuelle Seite") und können ihre eigenen Formulare,
622     Links etc. erzeugen die mit anderen Applikationen nicht kollidieren. In
623     einer Anwendung verwende ich dasselbe Forum-Element, um "Web Chat",
624     "Kleinanzeigen" und eine "News!"-Seite zu implementieren - jedesmal eine
625     leicht andere Konfiguration aber derselbe Code.
626    
627     Da PApp-Applikationen im Prinzip nur grosse Statemaschinen sind (das ist
628     eine Einschränkung der verwendeten Protokolle, d.h. bis Perl effektive
629     und schnelle continuations bekommt ;), kann man sie auch einfach in andere
630     einbauen. Sie können sich gegenseitig beeinflussen, treten sich aber
631     nicht auf die Füsse.
632    
633 root 1.3 Also im Prinzip genauso wie ein "Widget" in X11 oder gtk+.
634 root 1.2
635     H2: Logging/Protokollierung
636    
637     PApp protokolliert wesentlich mehr, als man benötigt, legal wäre, und
638     speicherbar wäre. Da PApp jederzeit in der Lage sein muss, eine ältere
639     Seite zu regenerieren ("Back & Reload"), speichert es pro Seite die
640     persistenten Variablen (ca. 300-900 Byte, je nach Applikation, das ist,
641     wie gesagt, auch eine tolle Sache zum Debuggen).
642    
643     Aber irgendwann müssen diese Daten wieder weg bzw. statistische Daten
644     her - nichts ist interessanter, als Zugriffsmuster, Voreinstellungen oder
645     ähnliches, an dem man ablesen kann, welche Dinge beliebt sind und welche
646     nicht (klar, man kann auch ganz andere Sachen auswerten, aber das ist
647     nicht mein Problem).
648    
649     Beim Aufräumen spielt PApp die einzelnen Zugriffe noch einmal
650     durch. Statt jedoch Seiten zu erzeugen gibt PApp den einzelnen
651     Applikationen die Möglichkeit, statistische Daten zu sammeln. Etwas
652     undokumentierter (wenn es da Abstufungen gibt) ist die Möglichkeit,
653     globale Daten zu sammeln, aber es geht...
654 root 1.1
655 root 1.2 H1: Eine einfache Anwendung mit PApp
656 root 1.1
657 root 1.3 Jetzt kommen wir zur eigentlichen Frage: Wie sieht so ein PApp-Programm
658     aus? Nun, meistens so:
659 root 1.1
660 root 1.3 H2: Das Hauptprogramm
661 root 1.1
662 root 1.3 !block verbatim
663     <package name="demo"> <domain lang="en">
664 root 1.1
665 root 1.3 <database dsn="DBI:mysql:demodb"/>
666 root 1.1
667 root 1.3 <translate fields="project.name place.name" lang="de"/>
668     <translate fields="project.description" lang="*" style="auto"/>
669 root 1.1
670 root 1.3 <import src="macro/util"/>
671 root 1.1
672 root 1.3 <include src="demo/somepages"/>
673    
674     </domain> </package>
675     !endblock
676    
677     Hmm... das ist also erstmal XML mit furchtbar vielen neuen
678     Elementen. Normalerweise kopiert man sich einfach ein anderes Programm
679     und schreibt nicht alles neu. Gut: zuersteinmal das C<package>-Element:
680     damit wird - genau wie in perl - ein neuer Namensraum erzeugt, der sowohl
681     normale Package-Variablen als auch State-Variablen enthält. Nicht jedes
682     Programm muss einen eigenen Namensraum öffnen.
683    
684     Das nächste Element, C<domain>, aktiviert die Übersetzungen: Alle
685     markierten Texte werden unter einem Namen, der C<domain>
686     gebündelt. Beispielsweise befinden sich alle Texte des PApp-Systems
687     selbst in der "papp"-Domain. Da im Beispiel kein Domainname angegeben
688     wird, nimmt PApp den Namen des umschleissenden C<package>-Elements, d.h.
689     wir definieren hier eine Übersetzungsdomain "demo".
690    
691     Das nächste Element deklariert die Standarddatenbank: Wird die
692     Datenbankhandle bei SQL-Abfragen weggelassen, wird diese Datenbank
693     benutzt. Normalerweise deklariert man Datenbanken aber nicht im Quellcode
694     sondern beim Einrichten der Anwendung im Konfigurationsmenü.
695    
696     Zu den nächsten beiden Elementen muss ich etwas über das Programm
697     erklären, das ich hier entwickeln möchte: Das Demo-Programm sollte
698     kurz sein und die wichtigsten Features von PApp zeigen. Es wird aus drei
699     (Web-) Seiten bestehen, eine Art Hauptseite mit einem Menü und zwei
700     Unterseiten, auf denen man ein Projekt auswählen kann (ein Projekt ist
701     ein einfacher Datensatz in der Datenbank, der den Projektnamen, den
702     Ort und die Beschreibung enthält). Auf der dritten Seite kann man die
703     einzelnen Felder eines Projektes ansehen und ändern.
704    
705     Als besonders überflüssiger Schnickschnack sollen die Projektdaten
706     übersetzbar sein, d.h. in der Sprache des Benutzers angezeigt werden. Das
707     ist nicht sehr wirklichkeitsnah, gibt dafür aber ein sehr simples
708     Beispiel ab.
709    
710     Da die Projektdaten in der Datenbank gespeichert sind, kann man
711     sie nicht einfach mit C<__"xxx"> markieren. sondern braucht ein
712     C<translate>-Element. Wo PApp die Übersetzungen herbekommt ist relativ
713     egal, man muss PApp nur sagen, wie es an die Texte herankommt und in
714     welcher Sprache sie sind.
715    
716     Das erste C<translate>-Element sagt, daß die Spalten C<name> in der
717     Tabelle <project> und die Spalte C<name> in der Tabelle C<place> in
718     Deutsch sind und dementsprechend in andere Sprachen zu übersetzen sind.
719    
720     Das zweite C<translate>-Element ist schon komplizierter: Nicht alle
721     Projektbeschreibungen sind in derselben Sprache (behaupte ich einfach
722     mal), weshalb als Sprache C<*> angegeben wird. Das bedeutet lediglich,
723     dass {{alle}} Übersetzer diese Texte übersetzen müssen. Wenn der
724     Englisch-Deutsch-Übersetzer also auf einen Deutschen Text stößt, muss
725     er ihn einfach überspringen. Wäre die Spalte als "de" (oder "deu")
726     markiert, würde er sie garnicht erst zu Gesicht bekommen.
727    
728     Da Beschreibungen ausserdem sehr lang sein können, erhält man mit
729     C<style="auto"> die Möglichkeit, die C<__"xxx">-Syntax auch in
730     den Beschreibungen zu verwenden. Dies kann man auch für einfache
731     Textbausteine mißbrauchen...
732    
733     Das darauffolgende C<import>-Element ist wieder etwas einfacher: es
734     entspricht mehr oder weniger der C<use>-Anweisung in Perl (in genau die
735     wird es auch übersetzt), bezieht sich aber auf PApp-Dateien. Damit
736     kann man Funktionen aus anderen (PApp-) Namensräumen importieren. Im
737     vorliegenden Fall importiere ich einfach mal das C<macro/util>-Paket, da
738     sich immer wieder grosser Beliebtheit erfreut.
739    
740     Das letzte Element tut zur Abwechslung genau das, was es sagt: es
741     fügt (logisch gesehen) eine andere Datei an dieser Stelle ein. Die
742     Entscheidung, die folgenden Seiten in eine andere Datei auszulagern lohnt
743     sich normalerweise nur für grössere Programme, aber so bleibt das
744     Beispiel klein.
745    
746     Bis jetzt tut sich noch nichts. Ändern wir das:
747    
748     H2: Das erste PApp-Modul
749    
750     Einzelne Zustände (z.B. Webseiten) werden bei PApp "Module" genannt, wohl
751     einzig um die Anwender zu verwirren. Diese Module werden meist in andere
752     Elemente (C<domain>, C<package>, C<style> etc..) verpackt, die auf die
753     Sete auf verschiedenste Weise einwirken.
754    
755     Ausführbaren Code kann man grundsätzlich auf zwei verschiedene Weisen
756     angeben: Normaler Perl-Code und Perl-Code gemischt mit Text (also wie bei
757     anderen embedded-Dialekten):
758 root 1.1
759 root 1.3 !block verbatim
760     <module name=""><phtml><![CDATA[
761     <html> <title>
762     __"PApp - demo", <?localtime:>
763     </title>
764    
765     <?slink "English", SURL_SET_LANG, 'en':>
766     <?slink "Deutsch", "/lang" => "de":>
767    
768     <p><?slink __"To the editor", "editor":>
769     <p><?slink __"Edit project 1", "editor", projectid => 1:>
770    
771     </html>
772     ]]></phtml></module>
773     !endblock
774    
775     Zuerst zum C<module>-Element: Jedes Modul besitzt einen eindeutigen
776     Namen. Das Standardmodul (das angezeigt wird, wenn nichts spezielles
777     ausgewählt ist, also sozusagen die Startseite) ist das Modul mit dem
778     leeren Namen: C<"">.
779    
780     Das Ergebnis eines Moduls sind die Ausgaben, die darin gemacht werden
781     (z.B. mit C<printf> oder dem PApp-C<echo>). Die Ausgabe des obersten
782     Moduls (im Baum) wird an den Browser geschickt. Für Ausgabe braucht man
783     Perl und das habe ich in ein C<phtml>-Element gepackt (für verbatimen
784     Perl-code würde man ein C<perl>- oder C<xperl>-Element verwenden, für
785     Perl gemischt mit XML gibt es noch C<pxml>).
786    
787     Innerhalb des C<phtml>-Elementes darf nur eine Zeichenkette stehen, die
788     ausgegeben wird. Da wir innerhalb der Zeichenkette Perl einbetten wollen
789     und die Modus-Umschalter {{kein}} gültiges XML sind, muss de rInhalt
790     geschützt werden, in diesem Fall mit einem C<CDATA> (die Verwending von
791     Abkürzungen in VI o.ä. empfiehlt sich ;)
792    
793     Da dies das oberste Modul ist und wir (noch) kein Stylesheet verwenden,
794     müssen wir eine ganz HTML-Seite ausgeben. Als Titel nehmen wir den Text
795     C<PApp-demo>, der übersetzt werden muss sowie, weil es so schön ist, die
796     aktuelle Uhrzeit. Dies geschieht mit einem {{C:<?}}: Der Ausdruck (hier
797     C<localtime>) wird in einem Skalaren Kontext ausgewertet und das Ergebnis
798     ausgegeben.
799 root 1.1
800 root 1.3 Die nächste Code-Zeile ist interessanter:
801 root 1.1
802 root 1.3 !block verbatim
803     <?slink "English", SURL_SET_LANG, 'en':>
804     !endblock
805 root 1.1
806 root 1.3 C<slink> ist PApps Art, eine Hypertext-Referenz (C<A>-Element) zu
807     erzeugen. C<slink> erwartet als erstes Argument den Inhalt des Verweises
808     (der Text, den der Benutzer "anklicken" muss) und daraufhin die
809     sogenannten C<surl>-Argumente, die bei vielen PApp-Funktionen angegeben
810     werden können.
811 root 1.1
812     %page
813    
814     phtml mode switches
815    
816    
817    
818     <: switch to perl statement mode
819    
820     <? evaluate perl expression
821    
822     :> switch to plain html/text mode
823    
824     ?> switch to interpolated (qq) html/text mode
825    
826    
827     %page
828    
829     Another simple module - "editor"
830    
831    
832     %font "t", prefix " "
833    
834     <module name="editor">
835     <state keys="projectid" local="yes"/>
836     <phtml><![CDATA[
837     <:header:>
838    
839     #if defined $S{projectid}
840     ... edit the specific project
841     #else
842     ... show a list of projects
843     #endif
844    
845     <:footer:>
846     ]]></phtml></module>
847    
848     %page
849    
850     SQL support - the project list
851    
852    
853     %font "t", prefix " "
854     <table><tr><th>__"Project"<th>__"Budget"
855     <:
856     my $st =
857     sql_exec \my($id, $name, $budget),
858     "select id, name, budget
859     from project";
860    
861     while ($st->fetch) {
862     :><tr><td>
863     <?slink gettext$name,
864     projectid => $id?>
865     <td>$budget
866     <:
867     }
868     :>
869     </table>
870    
871     %page
872    
873     SQL support - persistent rows
874    
875     %font "t", prefix " "
876     <:ef_begin:>
877    
878     <:my $row = new PApp::DataRef 'DB_row',
879     table => "project",
880     where => [id => $S{projectid}]:>
881    
882     <p>__"Name":
883     <:ef_string \$row->{name}, 40:>
884     <p>__"Budget":
885     <:ef_string \$row->{budget}, 8:>
886     <p>__"Description":
887     <:ef_text \$row->{description}, 60, 10:>
888    
889     <:ef_submit __"Update":>
890     <:ef_end:>
891    
892     %page
893    
894     Internationalization (I18n)
895    
896    
897    
898     Strings inside source files can be "tagged"
899    
900     Database columns can be tagged
901    
902     PApp is unicode-only
903    
904     Output conversion (e.g. utf8>latin1, utf8>iso2022jp)
905    
906     Translation editor ("poedit") included
907    
908     %page
909    
910     Speed
911    
912    
913    
914     Speed is slightly worse than Apache::Registry - on simple pages!
915    
916     Complex pages usually make no difference (database overhead!)
917    
918     Many PApp features deliver a performance that would be tedious to match in plain perl!
919    
920     PApp scales to many server machines, if necessary
921    
922     %page
923    
924     XML
925    
926    
927     No, XML is not a feature.
928    
929     XML might be nice to computers, it isn't usually for humans, though.
930    
931     XML is robust
932    
933     XML is fast
934    
935     XML is well supported
936    
937     %page
938    
939     XML + XSLT = protocol independency
940    
941    
942     PApp can support XML as well as HTML
943    
944     You can write your pages in XML
945    
946     XSLT stylesheets can be applied
947     at parse time
948     before module execution
949     to the resulting output
950    
951    
952     Thus, PApp applications can easily be made protocol-independent by writing them in XML and using a stylesheet that outputs either HTML, XML, WML or whatever you like!
953    
954     %page
955    
956     Dynamic stylesheet example
957    
958     %font "t", prefix " "
959     <perl><![CDATA[
960     $stylesheet[0] =
961 root 1.3 $papp->load_stylesheet("demo1");
962 root 1.1 $stylesheet[1] =
963 root 1.3 $papp->load_stylesheet("demo2");
964 root 1.1 ]]></perl>
965    
966     <style apply="output"
967     expr="$stylesheet[ $S{style} ]">
968    
969     <module name=""><phtml><![CDATA[
970     <p/><?slink __"To the edito...
971     <p/><?slink __"Edit projec...
972     ]]></phtml></module>
973    
974     ...
975     </style>
976    
977     %page
978    
979     "Web-Widgets"
980    
981    
982     A nice term - what is it?
983    
984    
985     PApp applications can be "embedded" into host applications
986    
987     With careful coding, reusable objects be created (e.g. a forum module, an ad-banner module etc.)
988    
989     Embedded apps come with their own state machine, own environment etc.
990    
991     Apply stylesheets to customize, if necessary
992    
993     %page
994    
995     PApp
996    
997    
998    
999    
1000    
1001     seperates
1002    
1003     layout
1004     semantics
1005     language
1006    
1007     from each other!
1008    
1009     %page
1010    
1011     Disadvantages
1012    
1013    
1014     perl 5.7.0 + patches is currently required
1015    
1016     many modules are necessary
1017    
1018     mod_perl is currently the only supported platform
1019    
1020     written by one overworked person only
1021    
1022     the api is in flux
1023    
1024     no stable release yet
1025    
1026     %page
1027    
1028     More info
1029    
1030    
1031    
1032    
1033    
1034    
1035    
1036    
1037 root 1.2
1038     Dabei ist PApp etwas sehr persönliches - ich habe meine persönlichen
1039     Vorstellungen davon, wie Web/CGI etc. funktionieren sollte, darin
1040     verwirklicht. Es hat meine Motivation (die sich mit "nie wieder CGI"
1041     zusammenfassen liess) gewaltig gesteigert - Ein einfaches aber dennoch
1042     komplettes Content-Management-System kann man in weniger als 500 Zeilen
1043     hinlegen - für mich ein wichtiger Faktor, denn ich hasse nichts mehr, als
1044     das Rad jedesmal neu erfinden zu müssen.
1045    
1046     H2: PApp is Free Software
1047    
1048     Although we are not sure wether we'll publish all versions of PApp
1049     under the GPL, or which modules from our own applications might become
1050     standard components (like the forum), we are determined to make PApp free
1051     software. The principal PApp architect (me!) did a lot of free software
1052     modules and works at quite a few free software programs (like GCC or The
1053     Gimp) and is determined to make PApp as free and as powerful as possible.
1054    
1055     H1: Disadvantages
1056    
1057     PApp is not actually a revolution, judged by its components. It
1058     does, however draw a lot of functionality and ideas into a single,
1059     well-contained package. Nevertheless, there are quite a few reasons on why
1060     {{NOT}} to use PApp, or at least not to use PApp {{YET}}.
1061    
1062     * PApp is not yet a released module, its API is in flux (with respect to
1063     recent features), and not everything is working as it should yet. This
1064     is fortunately only a question of time.
1065    
1066     * Only a single person is currently developing and designing PApp for
1067     free. This means that advances might sometimes not lead into the
1068     direction you want, and maybe not in the schedule you want.
1069    
1070     * PApp requires the very latest perl - at the moment, this is perl
1071     5.7 + custom patches, due to the buggy unicode support in earlier
1072     versions. The latest released PApp module (on CPAN) does not rely on
1073     unicode, but is already quite outdated with respect to current features.
1074    
1075     * There is a total lack of tutorials or introductory courses. While all
1076     PApp modules are documented, it is very much impossible to learn it
1077     using the reference documentation alone. Basically a one-day course
1078     under four eyes is necessary to get you up and running - PApp is
1079     not trivial. The lost time is generally made up with the increase in
1080     productivity experienced with PApp, though, similar to learning Perl ;)
1081    
1082     A1: References
1083    
1084     * PApp is available as a standard module from CPAN, although the current
1085     version uploaded is very old.
1086    
1087     * The PApp homepage is available at the author's homepage, under
1088     {{URL:http://www.goof.com/pcg/marc/papp.html}}. This page includes
1089     links to the current manpages. Online demos are, unfortunately, not yet
1090     available.
1091    
1092     * The newest versions of PApp can be accessed using CVS as a sourceforge project,
1093     at {{URL:http://www.sourceforge.net}}.
1094    
1095     * The slides for this presentation will be available at the author's
1096     homepage, at {{URL:http://www.goof.com/pcg/marc/docs.html}}, shortly
1097     after the linuxworldexpo.
1098    
1099     A2: Apology
1100    
1101     I'd like to apologize for any typoes or other mistakes in this
1102     document. It was written in a single session without access to a
1103     spellchecker and so has not been debugged it yet ;)
1104     %page
1105 root 1.1