Aus dem Aktienbestand werden zunächst ausgelesen 쮿 der Name der Aktie 쮿 die ISIN der Aktie 쮿 der URL der Aktie Im Anschluss daran werden die Daten des Einkaufs in das Datenfeld hinzugefü
Trang 1} $handle = fopen ($url, "r");
$data="";
while (!feof($handle)) $data = fgets($handle, 4096);
fclose ($handle);
// Kurs auslesen $search='<td class="column-datavalue2 last strong">';
else{
$ret[Kurs]=FALSE;
} // Datum und Zeit auslesen $search='<td class="column-datavalue2 last">';
$ret[Datum]=FALSE;
$ret[Zeit]=FALSE;
} return $ret;
} public function getDaten(){
Trang 2Im ersten Schritt wird die Methode ermittelnAktuelleDaten() beschrieben Die Homepage
bietet den kostenlosen Dienst an, stets aktuelle Börsenkurse bereitzustellen Abbildung5.16 zeigt die Darstellung der Daten in der HTML-Ausgabe Interessant ist dabei nebendem Preis auch das Datum und die Uhrzeit der Ermittlung des Kurses Es sollen dieDaten des Handelsplatzes Frankfurt verwendet werden, da unser Auftraggeber derRAUB-Bank ebenso den Handel an der Frankfurter Börse für seine Kunden anbietet
// $verkauf wären die aktuellen Verkaufsgebühren $akt=$this->ermittelnAktuelleDaten();
$data[ekSumme]=$data[ekEinzelpreis]*$data[anzahl]+$data[ekGebühr];
$data[aktGebühr];
$data[diffAktieEur]=$data[aktEinzelpreis]-$data[ekEinzelpreis];
1)*100; // ohne Kosten $data[gewinnEur]=$data[aktSumme]-$data[ekSumme]+$data[dividenden];
?>
Listing 5.11: Die neue Klasse „Bilanz“ (Forts.)
Trang 3Abbildung 5.16: Aktuelle Kursdaten der HTML-Datei
Der entsprechende HTML-Quellcode kann im Internetbrowser des Clients ausgelesenwerden Er ist im Folgenden dargestellt, wobei einige zusätzliche Zeilenumbrüche zurÜbersichtlichkeit eingefügt wurden:
Ähnlich wie bei einem Dateizugriff wird mit dem Befehl $handle = fopen ( ) unter
Angabe des URL eine Referenz auf die betreffende Homepage erstellt Vorher wirdjedoch geprüft, ob der URL-String nicht leer ist Eine leere oder auch ungültige Zeichen-
kette sorgt dafür, dass fopen blockiert und in einen Timeout läuft, der die Rückgabe der
Funktion stark verzögert
Die anschließende while-Schleife liest den HTML-Text der Seite so lange ein, bis das Ende erreicht ist Dabei werden mit dem Befehl $data = fgets($handle, 4096); jeweils 4kByte-Blö- cke eingelesen und der HTML-Quellcode als Zeichenkette in der Variablen $data gespei- chert Mit dem Befehl fclose ($handle); wird die Verbindung zur Internetseite dann wieder
geschlossen, deren Inhalt Sie nun als Zeichenkette vorliegen haben
Wie jede andere Zeichenkette, können Sie $data jetzt mit den mächtigen
Zeichenketten-funktionen von PHP durchsuchen Die erste Suche konzentriert sich auf die Zeichenfolge
<td class="column-datavalue2 last strong"> Die Position, an der die Zeichenfolge den wurde, wird unter $pos1 gespeichert Die Zeichenfolge kommt nur einmalig im
HTML-Code vor Die Position ist nicht größer als 0, wenn die Zeichenfolge nicht
gefun-den wurde In diesem Fall wird der ermittelte Kurswert auf $ret[Kurs]=FALSE; gesetzt.
Im Anschluss daran wird das nächste </td> hinter der gefundenen Position gesucht Dazwischen steht dann der Kurs, der extrahiert und in $AktKurs gespeichert wird Zusätzlich wird das Kommatrennzeichen über die Funktion str_replace in einen Punkt umgewandelt, sodass $AktKurs als Gleitkommazahl gesehen wird Auf diese Weise kann
man mit dem extrahierten Wert rechnen
Nach dem gleichen Prinzip werden das Datum und die Uhrzeit ausgelesen, zu der derKurs ermittelt wurde Hier wird nach der einmalig im HTML-Code vorkommenden Zei-
Trang 4chenkette <td class="column-datavalue2 last"> gesucht Da das Datum mit dd.mm.yyyy hh:mm ein festes Format und im Gegensatz zu einem Aktienkurs (1,23 € oder 123,45 €)eine feste Anzahl an Stellen hat, werden die nächsten 16 Stellen hinter der gesuchten Zei-
chenkette extrahiert Die ersten 10 Stellen werden als Datum in der Variablen $ret[Datum] und die Stellen 11 bis 15 als Uhrzeit in der Variablen $ret[Zeit] abgelegt Wenn dies nicht erfolgreich ist, werden diese beiden Variablen ebenfalls mit FALSE belegt Zur weiteren
Verarbeitung wird das Datenfeld mit dem Kurs, dem Datum und der Zeit dann als gabewert der Funktion zurückgegeben
Rück-Die zweite Methode der Bilanz, getDaten(), gibt die Ergebnisse der Bilanzberechnung als
Datenfeld zurück Aus dem Aktienbestand werden zunächst ausgelesen
쮿 der Name der Aktie
쮿 die ISIN der Aktie
쮿 der URL der Aktie
Im Anschluss daran werden die Daten des Einkaufs in das Datenfeld hinzugefügt Dazugehören
쮿 die Anzahl der Aktien im Bestand
쮿 die ggf erhaltenen Dividendenzahlungen
쮿 das Datum des Einkaufs (bzw der arithmetisch gewichtete Mittelwert bei mehrerenEinkäufen)
쮿 die Gebühren beim Einkauf
쮿 der Einzelpreis der eingekauften Aktien (bzw der arithmetisch gewichtete wert bei mehreren Einkäufen)
Mittel-Der nächste Teil der Bilanz ist abhängig davon, ob der Bestand bereits verkauft wurdeoder nicht Wenn er bereits verkauft wurde, so besitzt das Bilanzobjekt eine Verkaufsor-der Daraus werden extrahiert und dem Datenfeld hinzugefügt:
쮿 das Datum des Verkaufs
쮿 die Verkaufsgebühren
쮿 der Einzelpreis der Aktie, zu dem verkauft wurdeWurde der Bestand noch nicht verkauft, werden zunächst die aktuellen Daten von derHomepage ausgelesen Aus diesen Daten werden ausgegeben:
쮿 das aktuelle Datum
쮿 die Zeit, zu dem der Kurs ermittelt wurde
쮿 der aktuelle Einzelpreis, also der Kurs selbst Zusätzlich dazu werden die Verkaufsgebühren aus dem Konstruktor der Bilanz ausgege-ben, die bei einem Verkauf anfallen würden
Trang 5Im Anschluss daran werden die eigentlichen Berechnungen der Bilanz durchgeführt.
Dabei werden die folgenden Fakten ermittelt und in das Ausgabefeld $data hinzugefügt,
die auch später in der Ausgabe erscheinen sollen:
쮿 tageImBesitz beschreibt die Anzahl der Tage, die der Bestand schon existiert Dazu
wird das Datum des Einkaufs und das aktuelle Datum (entweder das jetzige Datum,falls der Bestand noch nicht verkauft wurde oder das Datum des Verkaufs) zunächst
in Sekunden umgewandelt mit der Funktion strtotime Die erhaltene Differenz der
beiden Werte ergibt dann die Anzahl der Sekunden, die der Aktienbestand im Besitzdes Anlegers war bzw ist Dividiert man den Wert durch 86 400, so erhält man dieAnzahl der Tage, die die Aktie im Besitz war bzw ist, da ein Tag 24 Stunden hat, eineStunde 60 Minuten und eine Minute 60 Sekunden hat (24x60x60=86 400)
쮿 ekSumme beschreibt den Betrag, die der Anleger für den Aktienbestand bezahlen
musste Sie besteht aus dem (durchschnittlichen) Kurs der Aktie beim Einkauf, pliziert mit der Anzahl der gekauften Aktien Hinzu kommen noch die angefallenenKaufgebühren
multi-쮿 aktSumme beschreibt den Wert des Bestands Dies ist der aktuelle Kurs bzw der
Ver-kaufskurs multipliziert mit der Anzahl Davon müssen die Verkaufsgebühren nochabgezogen werden
쮿 diffAktieEur ist die Differenz des Kurses beim Einkauf zu dem aktuellen Kurs bzw.
zum Kurs, zu dem verkauft wurde
쮿 diffAktieProz ist dieselbe Differenz, jedoch in Prozent Bei beiden Differenzen wird nur
der Kurs betrachtet und keine angefallenen Kosten und Dividendenzahlungen
쮿 gewinnEur ist der Gewinn (oder Verlust) in Euro, die der Aktienbestand abgeworfen
hat Dazu wird der Wert beim Einkauf vom aktuellen Wert des Bestands bzw derWert beim Verkauf abgezogen Da hier die Kosten bereits berücksichtigt sind, müssennur noch die erhalteten Dividenden hinzugefügt werden
쮿 gewinnProz ist dieser Gewinn, umgerechnet in Prozent.
쮿 gewinnProzProJahr rechnet den ermittelten Gewinn auf ein Jahr hoch Dazu wird der
erhaltene Gewinn durch die Anzahl der Tage geteilt, die sich der Aktienbestand imBesitz des Anlegers befindet Dann haben Sie den durchschnittlichen Gewinn pro Tagermittelt Dieser durchschnittliche Gewinn pro Tag wird mit den Tagen eines Jahres,also mit 365.25, wegen des Schaltjahres alle 4 Jahre, multipliziert Dieser Jahresge-winn wird dann noch in Prozent umgerechnet Dieser Wert dient zum Vergleich miteiner Festgeldanlage
Wenn Sie mit dem Aktienbestand Verlust gemacht haben, wäre gewinnProzProJahr
nega-tiv Da Sie jedoch selbst im Falle der Insolvenz der Aktiengesellschaft kein Geld zahlen müssen, wird der prozentuale Gewinn pro Jahr bei einem negativen Wert zum
drauf-Abschluss der Methode getDaten() auf 0 gesetzt.
Die Erweiterung der Klasse Aktienbestand sowie die Klasse Bilanz sorgen dafür, dass dieerwartete Ausgabe des Tests erfüllt wird Die einzelnen direkten Tests mit kleinen PHP-Skripten sind damit abgeschlossen Im nächsten Schritt wird nun die erste Benutzerober-fläche für unseren Auftraggeber erstellt
Trang 6Die zweite Phase: Die Schnittstelle zum Benutzer
Für den Prototyp der Benutzeroberfläche (GUI) wird eine Menüführung benötigt, durchdie unser Auftraggeber die von ihm definierten Anwendungsfälle (Abb 5.2) wieder fin-det Dadurch wird eine geschäftsprozessnahe Umsetzung der Anforderungen unter-stützt
Sowohl die Verwendung von JavaScript-Menüs als auch HTML-Frames sind veraltet Sieerlauben kein direktes Bookmarking und sind auch hinderlich für einen barrierefreienZugriff Die gesamte Darstellung soll daher in einer einzigen HTML-Datei möglichstohne Verwendung von aktiven Skripten beim Client erfolgen
Gleichzeitig sind Erweiterungen und Änderungen in der Menüführung sehr scheinlich Schon ab ca 50 Bildschirmmasken ist eine Änderung vom Entwickler oderDesigner nur nervenaufreibend konsistent durchzusetzen Die Bildschirmmasken wer-den also nicht vollständig auf dem Webserver gespeichert, sondern modular zusammen-gesetzt Für die kleine Beispielanwendung der Depotverwaltung genügt die in Abbil-dung 5.17 beschriebene Aufteilung
wahr-Abbildung 5.17: Aufteilung der Bedienführung
In der header.inc.php beginnt der HTML-Code Dort soll auch die PHP-Session des
Benut-zers initialisiert werden Die Menüführung soll auch einmalig in der Header-Datei gebracht werden
unter-Der zweite Teil der HTML-Ausgabe besteht aus dem eigentlichen Inhalt, den der zer ausgewählt hat Möchte er beispielsweise einen neuen Aktienbestand anlegen, sosind dazu einige Eingabeparameter nötig Diese Parameter sollen im Inhaltsteil in einem
Benut-HTML-Formular eingegeben werden Genau dies ist die Aufgabe der View im
MVC-Paradigma (Abb 3.28) Die Weiterleitung des ausgefüllten HTML-Formulars erfolgtdann an eine PHP-Datei, die den Controller des MVC darstellt Dort werden die eingege-benen Daten ggf auf Gültigkeit geprüft und an das Datenmodell übergeben Der Erfolgdieser Aktion wird dann wiederum an den Benutzer weitergegeben
Die footer.inc.php enthält dann lediglich einen einheitlichen Abschluss für die
HTML-Darstellung, wie eine Copyright-Information und das eigentliche Ende der HTML-Datei
Trang 7Die Realisierung des Konzepts erfolgt dadurch, dass jede PHP-Inhaltsdatei den Headerund den Footer inkludiert und diese beiden Dateien nur einmalig vorhanden sind Diesist der erste Ansatz für eine zentrale Verwaltung des Layouts und der Menüführung Beigrößeren Projekten wird ein solches Konzept weiter ausgebaut, indem die HTML-Dar-stellung von einem Objekt einer Template-Klasse übernommen wird Das Darstellungs-Template enthält dann unter anderem Eigenschaften für die Farbdarstellung und dengesamten Stil der Präsentation Dies kann beispielsweise über die Parametrierung desObjekts mit CSS-Dateien erfolgen.
Damit unser Auftraggeber die bislang nur exemplarisch getestete Funktionalität derPHP-Anwendung prüfen kann, wird in Abbildung 5.18 ein typisches Szenario in einemAktivitätsdiagramm auf Meeresspiegelebene (also auf der Ebene des Benutzers) zusam-mengestellt, welches einen Großteil der geforderten Anwendungsfälle abdeckt DiesesSzenario wird im Folgenden über das zu erstellende GUI abgedeckt
Abbildung 5.18: Szenario für die Schnittstelle zum Benutzer
Der erste Schritt besteht also darin, die Depotverwaltung zu starten Die entsprechendeInhaltsdatei soll eine leicht in HTML zu realisierende Willkommensmeldung darstellenund sowie das Menü der Depotverwaltung präsentieren Wie in jede Inhaltsdatei werdender Header und der Footer eingebunden Der Inhalt dieser beiden Rahmendateien wird
in den Listings 5.12 und 5.13 dargestellt
<?php session_start();
Trang 8<td><form action="laden.php" method="post">
<input type="submit" value=" laden "/>
</form></td>
<td><form action="speichern.php" method="post">
<input type="submit" value=" speichern " <?php echo $status?>/>
</form></td>
<td><form action="uebersicht.php" method="post">
<input type="submit" value="Übersicht / wählen" <?php echo $status?>/>
</form></td>
<td><form action="neu.php" method="post">
<input type="submit" value=" neu "/>
</form></td>
<td><form action="hinzukaufen.php" method="post">
<input type="submit" value=" hinzukaufen " <?php echo $status?>/>
</form></td>
<td><form action="dividende.php" method="post">
<input type="submit" value="neue Dividende" <?php echo $status?>/>
</form></td>
<td><form action="verkaufen.php" method="post">
<input type="submit" value=" verkaufen " <?php echo $status?>/>
</form></td>
</tr>
Listing 5.12: header.inc.php (Forts.)
Trang 9In der PHP-Session (Kap 2.2) wird vor allem die Liste der Aktienbestandsobjekte in der
Referenz $_SESSION[Bestand] verwaltet Zusätzlich wird festgehalten, wie viele bestände im Depot liegen ($_SESSION[BestandAnzahl]) und welcher Aktienbestand ggf ausgewählt wurde ($_SESSION[BestandGewählt]) Der gewählte Bestand kann über eine HTTP-Get Anfrage ($_GET[w]) an jede Datei übergeben werden, die die header.inc.php
Aktien-einbindet
Im Anschluss daran beginnt die Ausgabe des HTML-Codes Sie ist abhängig davon, obbereits ein Aktienbestand gewählt wurde oder nicht Ist dies nicht der Fall, wird
zunächst eine Statusvariable $status mit dem Textwert disabled belegt, die später im
Menü der HTML-Datei noch Verwendung findet Wurde bereits ein Bestand gewählt, sobleibt die Statusvariable leer Im zweiten Schritt wird das gewählte Aktienbestandsob-
jekt aus der Liste der Bestände in die Variable $bestandGewählt extrahiert Da die Liste der
Objekte in einer Session nicht direkt zugegriffen werden kann, muss das entsprechendeObjekt zunächst deserialisiert werden (Kap 4.1.2) Im Anschluss daran können Sie ausder Aktie des Bestands den Namen auslesen und ausgeben
Im Anschluss daran folgt im Header eine HTML-Tabelle mit einer Zeile und sieben ten, in der sich jeweils HTML-Formulare befinden, die auf die vom Auftraggeber defi-nierten Anwendungsfälle verweisen Sie bieten die Dienste an, um
Spal-쮿 Aktienbestände aus der Datenbank zu laden
쮿 Bestände wieder in die Datenbank abzuspeichern
쮿 eine Übersicht über alle Bestände anzuzeigen und ggf einen Bestand auszuwählen
쮿 einen neuen Bestand anzulegen
쮿 Aktien zu dem gewählten Bestand hinzuzukaufen
쮿 eine Dividende zu dem gewählten Bestand hinzuzufügen
쮿 den gewählten Bestand zu verkaufenWenn genau ein Bestand in der Depotverwaltung existiert, soll er stets angewählt sein.Wenn mehr als ein Aktienbestand existiert, muss stets genau ein Bestand angewählt sein
Zu Beginn der Anwendung existiert jedoch noch kein Bestand in der Depotverwaltung.Deshalb sind nur zwei Anwendungsfälle ausführbar, nämlich
쮿 Aktienbestände aus der Datenbank laden
쮿 einen neuen Bestand anlegen
Trang 10Alle anderen Anwendungsfälle können deaktiviert werden, indem die entsprechenden
Schaltflächen im HTML-Formular über den Text disabled grau dargestellt und inaktiv gesetzt werden Genau dies geschieht über die Ausgabe der Variablen $status, die entwe- der den Wert disabled enthält oder leer ist.
Die Footer-Datei enthält lediglich einen textuellen Copyright-Hinweis und das Ende derHTML-Datei
Die Willkommensseite ist die erste und einfachste Inhaltsseite Sie inkludiert den Headerund den Footer, die nun die Session verwalten, das Menü und den HTML-Rumpf
Wenn Sie nun die start.php ausführen, sehen Sie die in Abbildung 5.19 dargestellte
Trang 11Der nächste Schritt im Szenario besteht darin, einen neuen Aktienbestand anzulegen.
Dazu klicken Sie auf die Schaltfläche neu, die zu der Datei neu.php verweist Diese Datei
ist in Listing 5.15 dargestellt
<?php require_once("header.inc.php"); ?>
<form action="neu2.php" method="post">
<table border="0" width="100%">
<input type="text" name="kaufgebühr" size="10"/> ?
Listing 5.15: neu.php (View)
Trang 12Wie in jedem anderen Anwendungsfall werden auch hier der Header und der Footer gebunden Die Datei selbst besteht aus einer HTML-Tabelle, in der alle Parameter einge-geben werden, die zur Erstellung eines neuen Aktienbestands notwendig sind Sie könn-ten zusätzlich dazu clientseitige Gültigkeitsprüfungen – beispielsweise in einem Java-Skript – vornehmen, um den Benutzer frühzeitig auf Fehleingaben hinzuweisen.
ein-Das HTML-Formular der View verweist auf neu2.php, die eine Controller-Datei darstellt.
Die eingegebenen Daten werden per HTTP-POST-Protokoll übergeben Abbildung 5.20
zeigt zunächst die Eingabemaske der Datei neu.php.
Wenn Sie in Abbildung 5.20 nun auf OK oder Abbrechen klicken, werden alle nen Daten per HTTP-POST an die Datei neu2.php übertragen Deren Quellcode ist in Lis- ting 5.16 dargestellt Dort wird zunächst geprüft, ob Sie die Abbrechen-Schaltfläche betä- tigt hatten Dies ist noch vor der Einbindung der header.inc.php notwendig, da dort bereits
eingegebe-die Ausgabe des HTML-Codes zum Client beginnt In dem Fall, dass Sie den Vorgang
abbrechen wollen, werden Sie nämlich über das direkte HTTP-Kommando Location: start.php an start.php weitergeleitet Wenn die Ausgabe der HTML-Seite bereits begonnen
hat, ist eine solche Weiterleitung nicht mehr möglich
Trang 13Abbildung 5.20: Anlegen eines neuen Aktienbestands
Im Anschluss an die Einbindung der header.inc.php wird aus den eingegebenen Daten des Benutzers, die sich im PHP-Datenfeld $_POST befinden, zunächst ein neues Aktien-
objekt angelegt (vgl dazu den ersten Test in Listing 5.1)
Mit der angelegten Aktie und der zuvor in dem GUI eingegebenen Anzahl, dem Datum,Kurs und der Gebühr des Kaufs wird anschließend eine Kauforder erstellt, die wiede-rum zu einem Aktienbestand führt Das neu angelegte Bestandsobjekt wird dann in derSession serialisiert und die Anzahl der Bestände wird in der Session erhöht
Für die Ausgabe der Datei wird abschließend geprüft, ob das Anlegen des Bestandserfolgreich war oder nicht Dabei wird geprüft, ob der Bestand erfolgreich in der Sessiongespeichert wurde Im Erfolgsfall wird der neu angelegte Bestand in der Session ausge-wählt und eine Erfolgsmeldung ausgegeben, im Fehlerfall eine Fehlermeldung In bei-
Hinweis
Vor dem Anlegen der Aktie müsste eigentlich eine gründliche Prüfung der Inhalte
des $_POST-Felds vorgenommen werden, selbst wenn dies bereits auf der Seite des
Clients geschehen ist Viele Angreifer versuchen nämlich direkt, manipulierte POST-Kommandos auf die Controller-Dateien abzusetzen, um unberechtigtenZugriff auf den Datenbankserver zu erhalten
Trang 14HTTP-den Fällen muss die Meldung über die OK-Schaltfläche bestätigt werHTTP-den, die zu der noch
zu erstellenden Datei uebersicht.php führt.
Abbildung 5.21 zeigt die Erfolgsmeldung bei einem erfolgreich angelegten stand
echo "FEHLER beim Hinzufügen des Bestandes!";
Trang 15Abbildung 5.21: Ausgabe nach dem erfolgreichen Anlegen eines Aktienbestands
Durch das Drücken der OK-Schaltfläche wird nun mit dem gerade ausgewählten, neu angelegten Aktienbestand auf uebersicht.php zugegriffen In dieser Datei sollen die Bilan-
zen aller Bestände angezeigt werden, sodass man einen Überblick über sein Depot erhält.Zusätzlich soll man dort einen Bestand auswählen können, um mit diesem weitere Akti-onen durchzuführen, wie Aktien nachzukaufen, eine Dividende hinzuzufügen oder denBestand zu verkaufen Ein Großteil dieses Quellcodes ist in Listing 5.17 dargestellt
<?php require_once("header.inc.php"); ?>
<?phpfor($i=0;$i<$_SESSION[BestandAnzahl];$i++){
echo ' <a href="uebersicht.php?w='.$i.'">wählen </a><br>';
} echo $bilanz[anzahl].' Stück am '.$bilanz[ekDatum].' gekauft';