Thread Meldeliste auf Website erstellen (23 answers)
Opened by seemann at 2011-07-14 18:45

topeg
 2011-07-18 07:27
#150491 #150491
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Zielsetzung:
Auf einer Webseite sollen sich Personen eintragen können und sehen, ob sie sich eingetragen haben.

Gebraucht wird:
  • ein Speicherort für die Namen
    Die Liste sollte enthalten:
    • Vornamen
    • Name
    • Wohnort
    • Webseite
    • Mailadresse
    • Personen Beschreibung
    • Dienstzeit
    • Dienstgrad
    • Dienststellung
    • Einheit in der Gedient wurde
    • Schiff - Bordnummer
    • Schiff - Projekt
  • ein Script, welches das Eintragen der Daten übernimmt und diese anzeigen kann.


Mögliche Probleme:
Es werden Persönliche Daten eingetragen, die nicht für jeden einsehbar sein sollten (mit Name Anschrift und Email-Adresse kann man schon einigen Unsinn im Netz anstellen). Aus diesem Grund sollte der Zugang begrenzt werden. Ein Passwort, das der Nutzer bei der ersten Anmeldung eingibt würde schon helfen. Da das hier nirgendwo angesprochen wurde werde ich auch kein Passwort vorsehen.

Je nach Umfang der Daten kann es günstig sein ein Datenbank zu benutzen um diese zu speichern. Wenn Daten nur eingetragen aber nicht gelöscht oder geändert werden, so kann man auch ein einfache Datei nutzen, um die Daten zu speichern.
Ich gehe davon aus, dass es nur wenige Nutzer geben wird und das keine Änderungen vorgenommen werden sollen. Weshalb man problemlos auf eine Datei setzen kann.

Was soll das Script können:
  • es soll die Daten Annehmen und speichern
  • es soll die gespeicherten Daten anzeigen können

Daraus folgt das zwei grundsätzliche Funktionen gebraucht werden:
  • zeige_personen
    • die Anzeige soll alphabetisch sein
    • Von einer Zusammenfassung soll man zu der ausführlichen Ausgaben springen können
    • Die Ausführliche Liste soll alle gespeicherten Informationen in einer leiht Lesbaren Form enthalten
  • speicher_person
    • Die Eingaben sollen geprüft werden.
      • ob die Eingaben vollständig sind
      • ob die Person schon in der Liste existiert
    • Die Eingaben sollen gespeichert werden



Beginnen werde ich mit der Funktion speicher_person:
An sie über geben werden muss
  • Vornamen
  • Name
  • Wohnort
  • Webseite
  • Mailadresse
  • Personen Beschreibung
  • Dienstzeit
  • Dienstgrad
  • Dienststellung
  • Einheit in der Gedient wurde
  • Schiff - Bordnummer
  • Schiff - Projekt
  • Die Datei in der gespeichert werden soll

Geprüft werden muss ob folgende Angaben existieren:
Vornamen, Name, Wohnort, Mailadresse
Wenn eine davon nicht existiert, soll die Eingabemaske mit einer Warnung angezeigt werden.
Wenn die Kombination aus Vornamen, Name oder die Mailadresse in der Datei schon existiert, so soll die Eingabemaske mit einer Warnung angezeigt werden.
Wenn die Prüfung erfolgreich war sollen die Daten gespeichert werden und die Liste mit den Namen angezeigt werden.

Nun ist schon ersichtlich, dass eine weitere Funktion gebraucht wird um die Eingabemaske zusammen mit einer Möglichen Meldung anzuzeigen. Ich werde diese Funktion zeige_maske nennen.
zeige_maske hat als einzigen Parameter eine Mögliche Meldung.

Machen wie Funktion speicher_person etwas genauer:
  • lese Parameter
    • Vornamen
    • Name
    • Wohnort
    • Webseite
    • Mailadresse
    • Personen Beschreibung
    • Dienstzeit
    • Dienstgrad
    • Dienststellung
    • Einheit in der Gedient wurde
    • Schiff - Bordnummer
    • Schiff - Projekt
    • Die Datei in der gespeichert werden soll
  • prüfe ob
    • Vornamen nicht leer
    • Name nicht leer
    • Wohnort nicht leer
    • wenn Mailadresse vorhanden prüfe ob es eine gültige ist
      Wenn eine Prüfung fehlschlägt so rufe die Funktion zeige_maske mit der Meldung "Die Eingabe ist unvollständig!" auf
  • lese alle Daten
  • prüfe ob
    • Mailadresse oder
    • Name und Vornamen schon vorkommen

    Wenn das Fehlschlägt rufe die Funktion zeige_maske mit der Meldung "Diese Daten wurden schon eingetragen!" auf.
  • Hänge die neuen Daten an die Alten an
  • rufe zeige_personen auf



Zu zeige_personen
  • Hole die Datei
  • lese die Daten aus der Datei
  • Sortiere die Daten Alphabetisch nach Name und Vornamen
  • Gehe die Daten durch und Erzeuge mit Name und Voraname eine HTML-Liste
  • gib die Liste aus
  • Gehe die Daten durch und erzeuge eine HTML-Liste mit allen Daten
  • gib das HTML aus




Man kann schon sehen, dass die Datei mehrfach gelesen wird. Es wäre hier günstig Zu betrachten was alles mit der Datei gemacht wird.
Die Datei wird gelesen, durchsucht und es werden Daten angehängt.
So wie es jetzt aussieht wird die Datei zweimal gelesen, einmal wenn die Eingaben geprüft werden und ein anderes mal wenn die Daten Ausgeben werden.
Um das zu verhindern sollte man Die Dateizugriffe kapseln und die Zugriffe auf die Daten zu abstrahieren.

Hier bietet sich ein Objekt an, das es erlaubt:
  • einzelne Datensätze zu holen.
  • In den Datensätzen zu suchen.
  • Datensätze hinzu zu fügen.

das hat auch weiterhin den Vorteil, das man Das Objekt intern wahlweise mit DB-Zugriffen oder mit Datei-Zugriffen realisieren kann.
Ich werde es PersonenDB nennen.

[EDIT]Nicht vorhandenen Gedankengänge ergänzt
Es werden Methoden gebraucht, mit der man Die Daten sortieren lesen, suchen und schreiben kann.
Es wird also so etwas wie ein read sort get_by get_all und add gebraucht.
Mit read sollen die Daten geladen werden. Mit sort sollen die Daten im Speicher sortiert werden, sodass sie bei der Ausgabe durch get_by und get_all sortiert sind. An add sollen alle Daten übergeben werden, die für eine Person wichtig sind. Da bietet sich ein Hash, als Übergabeparameter an, da es viele Parameter sind und eine Sortierung nicht nötig. Das bedeutet aber dass die Klasse alle Erlaubten ParemeterNamen kennen muss, damit das Objekt sie in der richtigen Reihenfolge in die Datei schreiben kann und prüfen kann welche Parameter vorhanden sind. Da bei der Prüfung auch Fehler auftreten können ist es günstig diese im Objekt zu speichern und über eine Methode abfragbar zu machen. Als Mame der Methode bietet sich error an.

Fasse ich mal zusammen:
gebraucht werden:
Klassenparameter:
  • Liste aller Schlüssel die eine Person haben kann
  • Liste der Zwingend nötigen Parameter

Methoden:
  • read
  • add
  • sort
  • get_by
  • get_all
  • error

Nun werden noch die Objekt-Parameter gebraucht.
Das wäre zum einen eine Liste mit allen Personen, ein Parameter um die Fehler zu speichern und einer um den Dateinamen vor zu halten.

Will man nun beginnen die Methode read zu schreiben muss man sich Gedanken über das Dateiformat machen. Das einfachste ist ein CSV-Artiges Format zu nutzen. Dar Nachteil dabei ist, dass ASCII-Zeichen als Feldtrenner genutzt werden, die auch in den Feldern vorkommen können. Man kann sie entweder verbieten, oder ersetzen. Ich werde mich für das ersetzen entscheiden. Dazu muss ich alle Zeichen die Feldtrenner oder Zeilentrenner sind durch ein Folge von Zeichen ersetzen, die diese repräsentiert das wird im allgemeinen "entwerten" oder "quoten" genannt. Wenn ich als Feldtrenner ";" und als Zeilentrenner "\n" (bzw "\x0A") Benutzte, muss ich diese In den Feldern entwerten. Dazu nehme ich den ASCII wert der s zeichen als dreistellige zahl und setze ein % davor. das bedeutet auch dass % entwertet werden muss. Es wird eine Methode gebraucht die Alle Zeichen entwertet und eine die alle Entwertungen rückgängig macht.
Quote
quote
und unquote Das Lesen gestaltet sich nun wie folgt:


read:
  • öffne die Datei
  • lese sie zyklisch bis zum nächsten Zeilentrenner
  • trenne sie an den Feldtrennern
  • mach die Entwertung der geschützten Zeichen rückgängig
  • Speicher die werte im Objekt


das schreiben:
add
  • teste ob alle Paramter vorhanden
  • teste ob die Person schon eingetragen ist (hierzu bietet sie eine Methode exists an)
  • öffne die Datei wenn nötig
  • entwerte die geschützten zeichen
  • Erzeuge einen Dateieintrag durch zusammenfügen der Felder
  • hänge den Eintrag an die Datei an


sort
  • sortiere die liste nach Nachnamen, Vornamen und Adresse


get_by
  • filtere alle Einträge aus der Liste der Personen, die zu dem Feld die den richtigen Wert haben


Wenn man nun weiter konsequent weitermacht kann man zu einer Klasse ähnlich der die unten gezeigt wird kommen.
[/EDIT]
Jetzt wäre es nötig Die Klasse zum Objekt zu gestalten. Das kürze ich ab und springen direkt zur Implementation dieser zentralen Funktionalität:
PersonenDB.pm:
more (53.1kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
package PersonenDB;
use strict;
use warnings;
use IO::File;
use Fcntl qw(:flock :seek);
use utf8;

# Trenner
my $separator=";";
# Zeilenende
my $lineend="\x0A";

my @force_names=qw(vorname nachname address);
my @optional_names=qw(person website email dienstzeit dienstgrad dienststellung einheit nummer typ);
my @all_names=(@force_names,@optional_names);

my @typen=(
 ['Minenleger',     'KSS Projekt 1159 (Koni-class)'     ],
 ['Minenleger',     'MSR Projekt 89.2 (Kondor-class)'   ],
 ['U-Jagd',         'U-Jagd Projekt 133 (Parchim-class)'],
 ['Landungsschiff', 'LSM Projekt 108 (Frosch-class)'    ],
);

sub typen{ return @typen; }
sub key_names{ return @all_names; }

# PersonenDB->new($filename);
sub new
{
  my $class=shift;
  my $filename=shift;

  my $self={};
  $self->{filename}=$filename;
  $self->{data}    =undef;
  $self->{fh}      =undef;
  $self->{error}   ='';

  bless($self,$class);

  $self->read();

  return $self;
}

sub error
{
  my $self=shift;
  my $err=$self->{error};
  $self->{error}='';
  return $err;
}

# Benutzer Sortieren
sub sort
{
  my $self=shift;

  @{$self->{data}}=sort __sort @{$self->{data}};

  return 1;
}

# generisches Golen von Nutzern
sub get_by
{
  my $self=shift;
  my $key=shift;
  my $val=shift;

  return __filter($self->{data},$key,$val);
}

# alle benutzer mit dem Vornamen
sub get_by_vorname
{
  my $self=shift;
  my $name=shift;

  return __filter($self->{data},'vorname',$name);
}

# alle Benutzer mit dem Nachnamen
sub get_by_nachname
{
  my $self=shift;
  my $name=shift;

  return __filter($self->{data},'nachname',$name);
}

# alle nutzer mit dem Vormanem und namen
sub get_by_name
{
  my $self=shift;
  my $vorname=shift;
  my $nachname=shift;

  my @l=__filter($self->{data},'nachname',$vorname);
  @l=__filter(\@l,'vorname',$nachname);
  return @l;
}

# allen Nutzter mit der Email
sub get_by_email
{
  my $self=shift;
  my $email=shift;
  return __filter($self->{data},'email',$email);
}

# Existiert person?
sub exists
{
  my $self=shift;
  my $user=shift;
  my @l=$self->get_by_name($user->{vorname},$user->{nachname});
  unless(@l)
  {
    @l=$self->get_by_email($user->{email});
    return 0 unless(@l);
  }
  return 1;
}

# daten lesen
sub read
{
  my $self=shift;

  # Datei öffnen:
  return 0 unless($self->_open());

  my $fh=$self->{fh};

  # Datei sperren
  flock($fh,LOCK_EX);

  # zum Anfang der Datei
  $fh->seek(0,SEEK_SET);

  # Liste leeren
  $self->{data}=[];

  # format:
  #   Vorname\0Name\0Wohnort\0Webseite\0Mailadresse\0Dienstzeit\0Dienstgrad\0Dienststellung\x0A
  # zeilen die mir '\s*#' starten werden ignoriert!
  local $/=$lineend;
  while(my $line=<$fh>)
  {
    chomp($line);
    next if($line=~/^\s*#/);
    $line=~s/^\s*//;
    next unless($line);

    my @data=map{__unquote($_)}split($separator,$line);
    push(@{$self->{data}},{map{$all_names[$_] => $data[$_]}(0..$#all_names)});
  }

  # Datei entsperren
  flock($fh,LOCK_UN);

  # Liste sortieren:
  $self->sort();


  return 1;
}

# Person hinzufügen
sub add
{
  my $self=shift;
  my $data=shift;

  # nicht hinzufügen wenn nicht alle wichtigen daten vorhanden
  for(@force_names)
  {
    unless($data->{$_})
    {
      $self->{error}.= sprintf("%s ist Leer!\n",$_);
      return 0;
    }
  }

  # unnötige werde auf '' setzen.
  for(@optional_names)
  { $data->{$_}='' unless($data->{$_}); }

  # testen ob die Emailadersse korrekt ist
  if($data->{'email'})
  {
    unless($data->{'email'}=~/^[\w._%+-]+@[\w.-]+\.\w{2,4}$/)
    {
      $self->{error}.= sprintf("%s ist keine korrekte Emailadresse!\n",$data->{'email'});
      return 0;
    }
  }

  # nicht hinzufügen wenn schon vorhanen
  if($self->exists($data))
  {
    $self->{error}.= "Der Name ist schon Eingetragen!\n";
    return 0;
  }

  # Datei öffnen wenn nicht schon offen:
  return 0 unless($self->_open());

  # Daten serialisieren
  my $string="  ".join($separator,map{__quote($data->{$_})}@all_names).$lineend;

  my $fh=$self->{fh};

  # Datei sperren
  flock($fh,LOCK_EX);

  # zum Ende der Datei:
  $fh->seek(0,SEEK_END);

  # schreiben
  $fh->print($string);

  #das schreiben der Daten erzwingen
  $fh->flush();
  $fh->sync();

  # Datei Entsperren
  flock($fh,LOCK_UN);

  # zur Liste hinzufügen
  push(@{$self->{data}},$data);

  # sortieren
  $self->sort();

  return 1;
}

# alle Daten
sub all
{
  my $self=shift;
  return @{$self->{data}};
}

########################################################################
# privat

sub _open
{
  my $self=shift;
  # Datei öffnen wenn nicht offen
  $self->{fh}=IO::File->new() unless($self->{fh});
  if(!$self->{fh}->opened())
  {
    unless($self->{fh}->open($self->{filename},"+>>"))
    {
      $self->{error}.= "Die Datenbank lässt sich nicht öffnen!\n";
      return 0;
    }
  }
  return 1;
}

# sortierung
sub __sort
{
  for (qw(nachname address vorname))
  {
    my $x=lc($a->{$_}) cmp lc($b->{$_});
    return $x if($x != 0);
  }
  return 0;
}

# Geschützte Zeichen Entwerten
sub __quote
{
  my $val=shift;
  $val=~s/(%|\Q$separator\E|\Q$lineend\E)/'%'.join('%',map{sprintf('%03u',ord($_))}split('',$1))/egs;
  return $val;
}

# Entwertung rückgängig machen
sub __unquote
{
  my $val=shift;
  $val=~s/%(\d\d\d)/chr($1)/egs;
  return $val;
}

sub __filter
{
  my @liste=@{shift()};
  my $key=shift;
  my $value=shift;

  for my $pos (reverse(0..$#liste))
  {
    my $v=$liste[$pos];
    splice(@liste,$pos,1) if(!exists($v->{$key}) || $v->{$key} ne $value);
  }

  return @liste;
}

1;


[EDIT]Gedanken ergänzt:
Wie man sehen kann ist die gesamte Prüfung in den Code für die DB gewandert. Dadurch entfallen sämtliche Prüfungen im Script. Diese muss nur noch prüfen, ob eine Aktion erfolgreich war. Außerdem mache ich einen "Lock" auf die Datei, um Kornkurierende Schreib/Lesezugriffe zu kontrollieren. Das verhindert zerstörte Einträge wenn zwei Personen sich gleichzeitig eintragen wollen.
[/EDIT]

Die Klasse sollte man auch gleich testen:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/perl
use strict;
use warnings;
use PersonenDB;

# Für Tastausgaben
use Data::Dumper;

my $db = PersonenDB->new('test.dat');

#print Dumper($db); exit();

$db->add({
    vorname        => 'Test',
    nachname       => 'Tester',
    address        => 'TestStr 1',
    website        => 'www.test.de/test2',
    email          => 'mail@test.de',
    dienstzeit     => 100,
    dienstgrad     => '1',
    dienststellung => '1965.1.12',
    einheit        => 'rable',
    nummer         => 837,
    typ            => 4,
    person         => 'das ist nur ein test!',
  }) || print "ERROR:".$db->error()."\n";

$db->add({
    vorname        => 'Toto',
    nachname       => 'Testerito',
    address        => 'TestStr 22',
    website        => 'www.test.de/test1',
    email          => 'mail1@test.de',
    dienstzeit     => 100,
    dienstgrad     => '2',
    dienststellung => '1965.1.12',
    einheit        => 'blub',
    nummer         => 837,
    typ            => 2,
    person         => 'das ist nur ein test!',
  }) || print "ERROR:".$db->error()."\n";

$db->add({
    vorname        => 'Tranta',
    nachname       => 'Tester',
    address        => 'TestStr 1',
    website        => 'www.test.de/test3',
    email          => 'mail2@test.de',
    dienstzeit     => 100,
    dienstgrad     => '3',
    dienststellung => '1923',
    einheit        => 'bla',
    nummer         => 11234,
    typ            => 1,
    person         => 'das ist nur ein test!',
  }) || print "ERROR:".$db->error()."\n";

$db->add({
    vorname        => 'Karl',
    nachname       => 'Boratis',
    address        => "Rabenweg 19293\n12345 Braurig",
    website        => 'www.test.de/test3',
    email          => 'mail3@test.de',
    dienstzeit     => 100,
    dienstgrad     => '4',
    dienststellung => "2.11.1968",
    einheit        => 'bla',
    nummer         => 4,
    typ            => 4,
    person         => 'das ist nur ein test!',
  }) || print "ERROR:".$db->error()."\n";

$db->add({
    vorname        => 'Henry',
    nachname       => 'Boratis',
    address        => "Rabenweg 19293\n12345 Braurig",
    website        => 'www.test.de/test4',
    email          => 'xxx???&test.??',
    dienstzeit     => 100,
    dienstgrad     => '4',
    einheit        => 'luba',
    nummer         => 55,
    typ            => 3,
    person         => 'das ist nur ein test!',
  }) || print "ERROR:".$db->error()."\n";


print Dumper([$db->all()]);


Damit wäre die Datenbank fertig. Nun wird es Zeit sich über das HTML Gedanken zu machen. Es ist günstig HTML und Code zu trennen, das erleichtert nicht nur Übersichtlichkeit es erleichtert auch die Pflege und verhindert Fehler.
Ich werte CPAN:HTML::Template::Compiled nutzen.

Zuerst die Webseite zum eintragen der Personen:
input.tmpl
more (37.4kb):
Code (html): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Kameradenfinder/Meldeliste für Besatzungsmitglieder</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="description" content="Kameradenfinder/Meldeliste für Besatzungsmitglieder" />
    <style type="text/css">
      body {
        background-color:#ffffea;
        color:#ffff91;
        font-family:verdana;
        text-align:left;
      }
      #all {
        position:absolute;
        top:0px;
        left:50%;
        width:0px;
      }
      #document {
        position:relative;
        left:-350px;
        padding:0em;
        margin-top:3em;
        background-color:#000000;
        border-width:9px;
        border-style:outset;
        border-color:gray;
        width:700px;
      }
      #document_top {
        padding-top:2em;
        margin-bottom:2em;
        text-align:center;
      }
      #document_form {
        margin-top: 3em;
        padding:0em;
      }
      #document_send {
        margin-bottom:2em;
        margin-left:1em;
        margin-right:1em;

        padding-left:0em;
        padding-right:0em;
        padding-top:2em;
        padding-bottom:2em;

        border-left-width:0em;
        border-right-width:0em;
        border-top-width:0.2em;
        border-bottom-width:0.2em;
        border-color:#ffff91;
        border-style:solid;

        text-align:center;
      }
      #title {
        font-family:verdana,tahoma,arial;
        font-size:2em;
        margin-right:2em;
        font-weight:bold;
      }
      .link {
        font-family:verdana;
        color:#ffff91;
        font-size:1.2em;
      }
      #form_list {
        list-style-type:none;
        list-style-position:outside;
      }
      #form_list > li {
        padding: 0.2em;
      }
      .form_text {
        font-size:0.9em;
        text-align:left;
        width:13em;
        float:left;
        white-space:nowrap;
        font-weight:bold;
      }
      .form_input {
        float:none;
      }
      .form_input > input {
        font-size:0.5em;
        background-color: #ffffe1;
        font-weight: bold;
        width:40em;
      }
      .form_input > textarea {
        font-size:0.5em;
        background-color: #ffffe1;
        font-weight: bold;
        width:40em;
        height:10em;
      }
      .form_input > select {
        font-size:0.5em;
        background-color: #ffffe1;
        font-weight: bold;
        width:40em;
      }
      #form_send {
        cursor: pointer;
        background-color: #00ff00;
        color: #00004a;
        font-family: verdana;
        font-weight: bold;
        padding:0.3em;
        margin-right:2em;
      }
      #form_reset {
        cursor: pointer;
        background-color: #ff0000;
        color: #00004a;
        font-family: verdana;
        font-weight: bold;
        padding:0.3em;
        margin-right:4em;
      }
    </style>
  </head>
  <body><div id="all">
    <div id="document">
      <div id="document_top">
        <span id="title">Meldeformular</span>
        <a class="link" href="<TMPL_VAR ACTION_SHOW>" title="Meldeliste lesen...">Meldeliste lesen...</a>
      </div>
      <form action="<TMPL_VAR ACTION_SEND>" method="post">
      <input type="hidden" name="action" value="send" />
        <div id="document_form">
          <ul id="form_list">
            <li>
              <div class="form_text" >Name:</div>
              <div class="form_input"><input    name="nachname"       maxlength="30" size="50" value="<TMPL_VAR nachname>" /></div>
            </li>
            <li>
              <div class="form_text" >Vorname:</div>
              <div class="form_input"><input    name="vorname"        maxlength="30" size="50" value="<TMPL_VAR vorname>" /></div>
            </li>
            <li>
              <div class="form_text" >Wohnort:</div>
              <div class="form_input"><input    name="address"        maxlength="30" size="50" value="<TMPL_VAR address>" /></div>
            </li>
            <li>
              <div class="form_text">E-Mail:</div>
              <div class="form_input"><input    name="email"          maxlength="30" size="50" value="<TMPL_VAR email>" /></div>
            </li>
            <li>
              <div class="form_text" >Homepage:</div>
              <div class="form_input"><input    name="website"       maxlength="30" size="50" value="<TMPL_VAR website>" /></div>
            </li>
            <li>
              <div class="form_text" >Zur Person:</div>
              <div class="form_input"><textarea name="person"         rows="4" cols="50" ><TMPL_VAR person></textarea></div>
            </li>
            <li>
              <div class="form_text" >Dienstzeit:</div>
              <div class="form_input"><input    name="dienstzeit"     maxlength="30" size="50" value="<TMPL_VAR dienstzeit>" /></div>
            </li>
            <li>
              <div class="form_text" >Dienstgrad:</div>
              <div class="form_input"><input    name="dienstgrad"     maxlength="30" size="50" value="<TMPL_VAR dienstgrad>" /></div>
            </li>
            <li>
              <div class="form_text" >Dienststellung:</div>
              <div class="form_input"><input    name="dienststellung" maxlength="30" size="50" value="<TMPL_VAR dienststellung>" /></div>
            </li>
            <li>
              <div class="form_text" >Einheit/Schiff:</div>
              <div class="form_input"><input    name="einheit"        maxlength="30" size="50" value="<TMPL_VAR einheit>" /></div>
            </li>
            <li>
              <div class="form_text" >Schiff - Bordnummer:</div>
              <div class="form_input"><input    name="nummer"         maxlength="30" size="50" value="<TMPL_VAR nummer>" /></div>
            </li>
            <li>
              <div class="form_text" >Schiff - Projekt:</div>
              <div class="form_input"><select   name="typ"            size="1" title="Typ auswählen">
                <option value="0" selected title="Schiffstyp auswählen">------------ Schiffstyp auswählen --------->>></option><TMPL_LOOP SELECT>
                <option value="<TMPL_VAR VALUE>" title="<TMPL_VAR TITLE>">&nbsp; <TMPL_VAR TEXT></option></TMPL_LOOP>
              </select></div>
            </li>
          </ul>
        </div>
        <div id="document_send">
          <input id="form_send"  title="Ich möchte mich in die Meldeliste eintragen." type="submit" value="EINTRAGEN">
          <input id="form_reset" title="Alles Mist noch mal neu."                     type="reset"  value="LÖSCHEN">
          <a class="link" href="<TMPL_VAR ACTION_SHOW>" title="Meldeliste lesen...">Meldeliste lesen...</a><br />
          <p><TMPL_VAR MESSAGE></p>
        </div>
      </form>
        &nbsp;
    </div></div>
  </body>
</html>

nun noch das HTML für die Liste:
show.tmpl
more (30.5kb):
Code (html): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Kameradenfinder/Meldeliste für Besatzungsmitglieder</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="description" content="Kameradenfinder/Meldeliste für Besatzungsmitglieder" />
    <style type="text/css">
      a {
        font-family:verdana;
        color:#ffff91;
        font-size:1em;
      }

      body {
        background-color:#ffffea;
        color:#ffff91;
        font-family:verdana;
        text-align:left;
      }

      #all {
        position:absolute;
        top:0px;
        left:50%;
        width:0px;
      }
      #document {
        position:relative;
        left:-350px;
        padding:0em;
        margin-top:3em;
        background-color:#000000;
        border-width:9px;
        border-style:outset;
        border-color:gray;
        width:700px;
      }
      #document_top {
        padding-top:2em;
        margin-bottom:2em;
        text-align:center;
      }
      #document_form {
        margin-top: 3em;
        padding:0em;
      }
      #personen_short {
        margin-bottom:2em;
        margin-left:1em;
        margin-right:1em;

        padding-left:0em;
        padding-right:0em;
        padding-top:2em;
        padding-bottom:2em;

        border-left-width:0em;
        border-right-width:0em;
        border-top-width:0.2em;
        border-bottom-width:0.2em;
        border-color:#ffff91;
        border-style:solid;

        text-align:left;
      }
      #personen_short ul {
        list-style-type: none;
      }
      #personen_short li {
        display: inline;
      }
      #personen_short li > a {
        min-width: 9em;
        display: -moz-inline-box;
        display: inline-block;
      }

      #personen_long {
        list-style-type: none;
        margin: 0em;
        padding: 0em;
      }

      #personen_long > li {
        padding-bottom:1em;
        margin: 1em;
        border-left-width:0em;
        border-right-width:0em;
        border-top-width:0em;
        border-bottom-width:0.2em;
        border-color:#ffff91;
        border-style:solid;
      }

      #personen_long > li > ul {
        margin: 0em;
        padding: 0em;
        list-style-type: none;
      }

      #document_bottom {
        margin-top:2em;
        margin-left:1em;
        margin-right:1em;

        padding-bottom:2em;
        padding-top:2em;

        border-left-width:0em;
        border-right-width:0em;
        border-top-width:0em;
        border-bottom-width:0.2em;
        border-color:#ffff91;
        border-style:solid;
        text-align:center;
      }

      #title {
        font-family:verdana,tahoma,arial;
        font-size:2em;
        margin-right:2em;
        font-weight:bold;
      }
      .link {
        font-size:1.2em;
      }

      .p_typ {
        font-size:0.8em;
        text-align:left;
        width:13em;
        float:left;
        white-space:nowrap;
      }

      .p_txt {
        float:none;
        font-size:0.8em;
        width:40em;
      }
    </style>
  </head>
  <body><div id="all">
    <div id="document">
      <div id="document_top">
        <span id="title">MeldeListe</span>
        <a class="link" href="<TMPL_VAR ACTION_INPUT>" title="Person Eingeben...">Person Eingeben...</a>
      </div>
      <div id="personen_short">
        <a name="TOP">NAMEN:</a>
        <ul><TMPL_LOOP PERSON>
          <li><a href="#<TMPL_VAR ANKER>"><TMPL_VAR KURZNAME></a></li></TMPL_LOOP>
        </ul>
      </div>
      <ul id="personen_long">
        <TMPL_LOOP PERSON>
        <li>
          <a name="<TMPL_VAR ANKER>" href="#top">Nach Oben</a>
          <ul>
            <li>
              <div class="p_typ" >Name:</div>
              <div class="p_txt"><TMPL_VAR nachname></div>
            </li>
            <li>
              <div class="p_typ" >Vorname:</div>
              <div class="p_txt"><TMPL_VAR vorname></div>
            </li>
            <li>
              <div class="p_typ" >Wohnort:</div>
              <div class="p_txt"><TMPL_VAR address></div>
            </li>
            <li>
              <div class="p_typ">E-Mail:</div>
              <div class="p_txt"><TMPL_VAR email></div>
            </li>
            <li>
              <div class="p_typ" >Homepage:</div>
              <div class="p_txt"><TMPL_VAR website></div>
            </li>
            <li>
              <div class="p_typ" >Zur Person:</div>
              <div class="p_txt"><TMPL_VAR person></div>
            </li>
            <li>
              <div class="p_typ" >Dienstzeit:</div>
              <div class="p_txt"><TMPL_VAR dienstzeit></div>
            </li>
            <li>
              <div class="p_typ" >Dienstgrad:</div>
              <div class="p_txt"><TMPL_VAR dienstgrad></div>
            </li>
            <li>
              <div class="p_typ" >Dienststellung:</div>
              <div class="p_txt"><TMPL_VAR dienststellung></div>
            </li>
            <li>
              <div class="p_typ" >Einheit/Schiff:</div>
              <div class="p_txt"><TMPL_VAR einheit></div>
            </li>
            <li>
              <div class="p_typ" >Schiff - Bordnummer:</div>
              <div class="p_txt"><TMPL_VAR nummer></div>
            </li>
            <li>
              <div class="p_typ" >Schiff - Projekt:</div>
              <div class="p_txt"><TMPL_VAR typ></div>
            </li>
          </ul>
        </li></TMPL_LOOP>
      </ul>
      <div id="document_bottom">
        <a class="link" href="<TMPL_VAR ACTION_INPUT>" title="Person Eingeben...">Person Eingeben...</a>
      </div>
      &nbsp;
    </div></div>
  </body>
</html>



Und nun zum eigentlichen Code.

durch die Verwendung einer Klasse, das die Dateizugriffe kapselt, verändern sich die Parameter, die an die Funktionen übergeben werden und die Abläufe ein wenig. Im großen und ganzen bleiben die Funktionalitäten aber erhalten.

Da man sich schon Geadnken über den Aufbau gemacht hat, ist die Implementation nicht mehr so schwehr. Durch die saubere Abtrennung der Datenhaltung und dem HTML ist der Code sehr übersichtlich und ist nur die Verbindung zwischen den Daten und dem HTML

liste.pl
more (27.4kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/perl
use strict;
use warnings;
use HTML::Template::Compiled;
use CGI;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use PersonenDB;
use utf8;

# die benötigten Dateien
my $input_tmpl='input.tmpl';
my $show_tmpl='show.tmpl';
my $db_file='test.dat';

# Die Objkete erzeugen.
my $cgi  = CGI->new();
my $db   = PersonenDB->new($db_file);

# Ausgabe beginnen
print $cgi->header(-type=>"text/html", -charset=>"UTF-8");

# warungen in den Browser Ausgeben
warningsToBrowser(1);

# die gewünscht aktion bestimmen
my $action=lc($cgi->param('action') || '');
# wenn es keine bekannte Aktion ist, dann soll es 'show' sein
$action='show' unless(grep{$action eq $_}qw(show input send));

# Eingabemaske Zeigen
if($action eq 'input')
{
  zeige_maske($cgi,$db,$input_tmpl,{},'');
}
# Daten senden
elsif($action eq 'send')
{
  speicher_person($cgi,$db);
}
# Daten Anzeigen
else
{
  zeige_personen($cgi,$db,$show_tmpl);
}

# Eingabemaske generiegen und anzeigen
sub zeige_maske
{
  my $cgi=shift;
  my $db=shift;
  my $file=shift;
  my $user=shift || {};
  my $message=shift || '';
  my $tmpl = HTML::Template::Compiled->new(
    cache    => 0,
    filename => $file,
  );


  my %data;
  for my $key ($db->key_names())
  { $data{$key}=$user->{$key} || ''; }

  my @tmp=$db->typen();
  my @sel;
  for(1..@tmp)
  {
    my $v=shift(@tmp);
    push(@sel,{
        VALUE => $_,
        TITLE => $v->[0],
        TEXT  => $v->[1],
      });
  }

  $tmpl->param(
      MESSAGE     => $message,
      ACTION_SHOW => $cgi->script_name()."?action=show",
      ACTION_SEND => $cgi->script_name(),
      SELECT      => \@sel,
      %data,
    );

  print $tmpl->output();

  return 1;
}

# Daten lesen und Person speichern
sub speicher_person
{
  my $cgi=shift;
  my $db=shift;

  my %nutzer;
  for my $key ($db->key_names())
  { $nutzer{$key}=$cgi->param($key); }

  if($db->add(\%nutzer))
  { zeige_personen($cgi,$db,$show_tmpl); }
  else
  { zeige_maske($cgi,$db,$input_tmpl,\%nutzer,$db->error()); }

}


# Liste Generieren und anzeigen
sub zeige_personen
{
  my $cgi=shift;
  my $db=shift;
  my $file=shift;
  my $tmpl = HTML::Template::Compiled->new(
    cache    => 0,
    filename => $file,
  );

  my @typen=$db->typen();

  my $cnt=0;
  my @personen;
  for ($db->all())
  {
    my $person={%$_};

    $person->{ANKER}="anker$cnt";
    $person->{KURZNAME}="$person->{vorname} $person->{nachname}";

    if($person->{typ}<=0 || $person->{typ}>@typen)
    { $person->{typ}=''; }
    else
    {
      my $t=$typen[$person->{typ}-1];
      $person->{typ}="$t->[1] ($t->[0])";
    }

    push(@personen,$person);
    $cnt++;
  }

  $tmpl->param(
      ACTION_INPUT => $cgi->script_name()."?action=input",
      PERSON       => \@personen,
    );

  print $tmpl->output();
}


Es ist alles nicht so schwehr.
Last edited: 2011-07-18 14:22:16 +0200 (CEST)

View full thread Meldeliste auf Website erstellen