Webtechnologien Wintersemester 2024

 

Quelle: Ian Baker

  • 22 Jahre isser, der kleine Hypertext Preprocessor.
  • Und er hatte es nicht leicht, wurde in der Jugend viel geärgert, ist aber in den letzten Jahren eigentlich ganz cool geworden.
  • Powered angeblich über 80% der Websites

Geschichte

  • 1995 von Rasmus Lerdorf entwickelt, um Web-Entwicklung zu vereinfachen
  • Deswegen auch HTML-zentriert
  • C-Basis, Perl- und C-Syntax
  • Zend-Engine für bessere Ausführung dank Kompilierung und Code-Caches
  • Aktuell Version 7.1 (sehr lang 5, dann 6 übersprungen)
  • Urpsrünglich für kleine Homepage-Projekte und Nicht-Entwickler gedacht
  • Lerdorf: I don’t know how to stop it, there was never any intent to write a programming language […] I have absolutely no idea how to write a programming language, I just kept adding the next logical step on the way.
  • Zend: Interpreter und virtuelle Maschine, ähnlich zu Java wird Bytecode generiert (Zend-Opcode), der gecached werden kann
  • Entstanden ist eine objektorientierte, funktionale (und imperative, prozedurale, reflektive), garbage collectete, interpretierte Skriptsprache
  • freie Software unter PHP License
  • nicht spezifiziert, Interpreter = Defacto-Standard (seit diesem Jahr Arbeit an Spezifikation)

Beispiel

<?php
   $link = 'http://www.cinestar.de/de/kino/berlin-cinestar-original-im-sony-center/veranstaltungen/original-sneak-mysterie-movie-ov/';
   $html = file_get_contents($link);
   if (strpos($html, 'time_table_container') == false) die;

   $to      = 'beierm@htw-berlin.de';
   $subject = 'Tickets können jetzt reserviert werden.';
   $message = "Go go go: $link";
   $headers = 'From: "Sneak-Scanner" <beierm@htw-berlin.de>';

   mail($to, $subject, $message, $headers);
?>
  • Keine Main-Funktion – es geht einfach los

Kritik

  • Keine Sprache, sondern eine willkürliche Sammlung an Funktionalität.
  • ⋯ und die sind auch noch inkonsistent benannt.
  • PHP-Code wird unausweichlich chaotischer, unwartbarer Mist.
  • PHP ist das Nickelback der Programmiersprachen.
  • Aber Facebook, Wikipedia und WordPress nutzen PHP!
  • große Liste an Kritikpunkten: PHP: a fractal of bad design
  • Nie designed, eher organisch entwickelt und viele Funktionen nur C-Wrapper
  • laut PHPs Function and Method listing derzeit knapp 10k Funktionen, davon ein paar hundert Kern
  • Spaghetti SQL wrapped in spaghetti PHP wrapped in spaghetti HTML, replicated in slightly-varying form in dozens of places
  • Aber Facebook, und Wikipedia, und WordPress: Schlechtes Argument: Path Dependence (= a logical decision in the past leads to a suboptimal system in the present), Altstadt-Problem, Dvorak
  • Sehen wir PHP nicht als Werkzeug sondern als Material: Holz oder Stein – nichts ist per se besser, um ein Haus zu bauen; es kommt nur darauf an, was für ein Haus.
  • Und wer Software bauen möchte, die frei ist, auf nahezu jedem Server läuft und das reibungsfrei und ohne Konfiguration …
  • Und von den Millionen Kritikern hat es bisher niemand geschafft, eine ordentliche Alternative zu bauen
  • Kurzum: Sie ermöglicht es, bestimmte Aufgaben sehr leicht zu lösen, kann aber bei größeren Aufgaben Probleme mitbringen

Aufbau

Client Server

Quelle: Wikipedia

  1. Webserver (nicht file://!) bekommt Anfrage
  2. Wenn .php (Kann auch alles andere sein, aber Server muss entsprechend konfiguriert werden)
  3. Lädt Datei von Festplatte (DOCUMENT_ROOT)
  4. Übergibt Datei an PHP-Interpreter
  5. PHP-Interpreter (CGI oder Server-Modul) arbeitet alles ab (Serverseitig – es wird also nur Resultat der Verarbeitung übermittelt, kein Code)
  6. Gegebenenfalls Versand der Antwort
  • PHP per CGI: Für jede Anfrage wird vom Webserver (!) eine Instanz des PHP-Interpreters gestartet (wobei auch alle Ressourcen z.B. Datenbankverbindungen auf- und abgebaut werden)
  • PHP zustandslos wie HTTP (langsam, darum Bytecode-Caches)
  • Kann genauso gut für Kommandozeilenprogramme genutzt werden
  • Hierachie klarmachen: PHP kann JS generieren kann HTML generieren

Installation

<?php phpinfo(); ?>

Schlüsselwörter

​abstract​, ​and​, array(), ​as​, ​break​, ​case​, ​catch​, ​class​, ​clone​, ​const​, ​continue​, ​declare​, ​default​, ​do​, ​else​, ​elseif​, ​enddeclare​, ​endfor​, ​endforeach​, ​endif​, ​endswitch​, ​endwhile​, ​extends​, ​final​, ​for​, ​foreach​, ​function​, ​global​, ​goto​, ​if​, ​implements​, ​interface​, ​instanceof​, ​namespace​, ​new​, ​or​, ​private​, ​protected​, ​public​, ​static​, ​switch​, ​throw​, ​try​, ​use​, ​var​, ​while​, ​xor

Konstanten

  • TRUE, FALSE, NULL, NAN
  • PHP_VERSION
  • PHP_EOL (OS-kompatibel, sonst nicht nötig)
  • E_ALL, E_ERROR, E_WARNING, E_PARSE, E_NOTICE
  • eigene definierbar
<?php define('NULLPUNKT', -273.15); ?>

<?php
   Class Temperature {
      const NULLPUNKT = -273.15;
   }
?>
  • gibt noch mehr, hier nur eine Auswahl
  • eigene Konstanten können nicht wie Variablen in Doublequote-Strings verwendet werden

Konstanten zur Kompilezeit

A.k.a. Magische Konstanten

​__CLASS__​ Name einer Klasse
​__DIR__​ Verzeichnisname der Datei
​__FILE__​ Vollständiger Pfad- und Dateiname
​__LINE__​ Aktuelle Zeilennummer einer Datei
​__FUNCTION__​ Name der Funktion
​__METHOD__​ Name einer Klassenmethode
​__NAMESPACE__ Name des aktuellen Namespaces
  • siehe Perl
  • __FUNCTION__ gibt nur Namen der Funktion zurück
  • __METHOD__ gibt Namen der Klasse und der Funktion zurück

Sprachkonstrukte

​die()​ Entspricht exit()
​echo​ Gibt einen oder mehrere Strings aus
​empty()​ Prüft, ob eine Variable einen Wert enthält
​exit()​ Gibt eine Meldung aus und beendet aktuelles Skript
​eval()​ Wertet eine Zeichenkette als PHP-Code aus
​include​ Bindet eine angegebene Datei ein und führt sie aus
​include_once​ include, aber pro Datei nur einmal ausgeführt
​isset()​ Prüft, ob Variable existiert und nicht NULL ist

Sprachkonstrukte

​list()​ Weist Variablen zu, als wären sie ein Array
​require​ Wie include, aber stirbt, wenn Datei fehlt
​require_once​ require, aber pro Datei nur einmal ausgeführt
​return​ Beendet Funktion oder Programm
​print​ Ausgabe eines Strings
​unset()​ Löschen einer angegebenen Variablen
​__halt_compiler() Beendet die Kompilerausführung
  • Wenn einzubindene Datei nicht vorhanden ist, generiert include eine Warnung und fährt vor, require hingegen wirft einen E_COMPILE_ERROR und beendet die Programmausführung.
  • return, return($var) aber nicht return()

Code

Einbettung

<!DOCTYPE html>
<html lang="de">
<head>
   <meta charset="utf-8">
   <title>Entscheidungshilfe</title>
</head>
<body>
   <h1>Soll ich es tun?</h1>
   <p><?php echo rand(0,1) ? "Ja" : "Nein"; ?>!</p>
</body>
</html>
  • Code kann direkt in HTML eingebettet werden
  • Parser sucht nach öffnenden und schließenden PHP-Tags (Anfangs- und Abschluss-Verarbeitungsinstruktionen) und wechselt vom HTML- in den PHP-Modus
  • Fehlenhafte Syntax (fehlende Semikolons, Klammern etc) führen zu Absturz

Einbettung

<!DOCTYPE html>
<html lang="de">
<head>
   <meta charset="utf-8">
   <title>Entscheidungshilfe</title>
</head>
<body>
   <h1>Soll ich es tun?</h1>
   <p>Ja!</p>
</body>
</html>

Tags und Kommentare

Code-Kommentare

Zeit: <?php echo date('H:i:s'); ?>
Zeit: <?= date('H:i:s') ?>

<?php
   // Kommentar
   #  Kommentar
   /* Kommen-
      tar */

   echo 'Ohne schließendes Tag Interpretation bis zum Ende';

Quelle: Michael Koziarski

  • Gibt noch andere Tag-Formen, die hier nicht behandelt und auch nicht verwendet werden sollten (Portabilität)
  • Kommentare in C- und Perl-Style
  • Schließendes Tag wird häufig weggelassen, um nicht versehentlich Whitespace zu senden, da dann Header nicht mehr verändert werden können
  • Zeilenumbruch ist Whitespace, Anweisungen werden mit Semikolon beendet

Variablen

  • Beginnen immer mit $
  • Dann Buchstabe oder Unterstrich, danach auch Zahlen
  • Case Sensitive
<?php $name = 'Waldo'; ?>
<strong>Hallo <?= $name ?>!</strong>
  • wieder wie in Perl (und Shell-Script)

Variablen

  • Haben Function-Scope (kein Block = global)
  • Datentypen: boolean, integer, float, string, array, object, resource, callable, null
  • Zugriff auf undefinierte Variable führt zu E_NOTICE, darum empty() oder isset() benutzen
<?php
   if (isset($var) && $var == 5) { echo 'Fünf'; }
?>
  • Datentyp wird durch Kontext ermittelt
  • 4 skalare, 2 mixed, 3 spezielle
  • Resource: Referenz zu einer externen Ressource (geöffnete Dateien, Datenbankverbindungen)
  • Null: repräsentiert eine Variable ohne Wert (case insensitive), kann nur NULL sein
  • callable: Callbacks und so

Variablen

  • PHP ist schwach und dynamisch typisiert
  • Ermittlung des Typs zur Laufzeit
  • Explizite Typangabe nicht unterstützt
  • Hinting schon, allerdings nur für Objekte, Arrays, Interfaces und Callbacks (… und alles andere ab php7)
  • Type Conversion / Type Coercion / Type Juggling
  • == vergleicht Wert (wenn nötig mit Typumwandlung)
  • === vergleicht Wert und Typ (ebenso !==)
  • Tabelle zu Typenvergleichen in PHP

Variablen

<?php
   $var *= ($var = 5); // 25
   $var = '5zig';
   echo (bool) $var; // 1 (auch: !!$var)
   settype($var, 'integer');
   echo $var; // 5
   $var == '5' // true
   $var === '5' // false
?>
  • müssen nicht deklariert und können sofort initialisiert werden (wenn schon vorhanden, dann wird überschrieben)
  • Zugriff, wenn nicht initialisiert, wirft Warnung, aber ist kein Fehler

Weitere Operatoren

  • + für Addition
  • . für String Concatenation (auch .= statt +=)
  • @ zur Fehlerunterdrückung
  • ++ für Inkrement
  • -- für Dekrement
<?php
echo '1' + 2 + '3'; // 6
echo '1' . 2 . '3'; // 123
echo 'Hallo ' . @$jibbet_nich; // Hallo
$var = 'y';
$var++; // z
++ $var; // aa
?>

Strings

<?php
   $name = 'Waldo';
   echo "Hallo \t $name"; // Hallo   Waldo
   echo 'Hallo \t $name'; // Hallo \t $name
   echo 'Alles Gute ' . $name;
   echo "Heute ist {$name}s Geburtstag";
   echo "Auch: ${name}, {$person->name} und {$person['name']}.";
   echo "Gib mir ein $name[0]! Gib mir ein $name[1]! … Und was macht das? $name!";
?>
  • Single / Double wie in Perl
  • Empfehlung: Immer Singlequote, wenn keine Doublequote-Features benötigt werden

Strings

<?php
$name = 'Waldo';

$content = <<<EOF
Werter Herr $name,\n
Ihre Nachricht mit dem Inhalt "'; DROP DATABASE --" wird
alsbald bearbeitet.
EOF;

echo 'Hier liegen ' . trim(`ls *.php | wc -l`) . ' PHP-Dateien';
?>
  • Dritte Art: Heredoc (Nowdoc als nicht interpolierte Variante)
  • Vierte Art: Backticks (synonym zur Shell, erlauben Variablen-Einschluss, aber Vorsicht!)

Kontrollstrukturen

<?php if (true): ?>
   <strong>Wahr.</strong>
<?php else: ?>
   <strong>Falsch.</strong>
<?php endif; ?>
<?php
if ($name == 'A') echo 'Hallo A';
elseif ($name == 'B')
   echo 'Hallo B';
else {
   echo 'Hallo';
}
?>
  • erste Form selten genutzt und eher für die Lesbarkeit in Verbindung mit HTML
  • funktioniert auch für Schleifen (while … endwhile, for … endfor, foreach … endforeach)
  • elseif eigenes Schlüsselwort (else if geht auch; Perl: elsif, Python: elif)
  • switch … case gibt es auch und verhält sich wie üblich
  • Yoda-Style um versehentliche Zuweisung statt Vergleich entgegenzuwirken

Logische Operatoren

<?php
$a && $b  // Und
$a and $b // TRUE wenn sowohl $a als auch $b TRUE ist.

$a || $b  // Oder
$a or $b  // TRUE wenn $a oder $b TRUE ist.

$a xor $b // Exklusives Oder
          // TRUE wenn entweder $a oder $b TRUE ist, aber nicht beide.

! $a      // Nicht – TRUE wenn $a nicht TRUE ist.
?>
  • Unterschiedliche Operator-Rangfolge: &&, ||, ?:, = += -= …, print, and, xor, or
  • $e = false || true ist nicht $e = false or true
  • trotzdem if ( ! $a = foo() )

Logische Operatoren

Geben immer boolschen Wert zurück (nicht Wert der Variablen).

<?php
   $var = 0 || 'foo';
   echo "Var: $var"; // Var: 1
   var_dump($var); // bool(true)

   // Setting defaults
   $name = $name || 'anonymous';          // NEIN
   $name = $name ? $name : 'anonymous'; // JA
   $name = $name ?? 'anonymous'; // ab PHP7
?>

Arrays

<?php    $neffen = array('Tick', 'Trick', 'Track');
         $zahlen = [1,2,3]; // Syntax seit PHP 5.4
         $tmnt = array(
            'Leonardo'     => 'two swords',
            'Michelangelo' => 'pair of nunchucks',
            'Raphael'      => 'pair of sai',
            'Donatello'    => 'bō staff',
         );
         $neffen[0] = 'Tock'; // ändern
         $neffen[] = 4;       // anhängen, Typ egal
         unset($neffen[2]);   // entfernen
?>
  • numerisch indexierte und assoziative Arrays (Hashs)
  • dynamische Länge
  • Typen können gemischt werden
  • Lücken möglich
  • Komma hinter letztem Eintrag unschön, aber möglich (und halt praktisch)
  • keine weiteren nativen Datenstrukturen (Bäume oder so)

Schleifen

<?php    $neffen = array('Tick', 'Trick', 'Track');
         $tmnt = array('Leonardo' => 'two swords'); // etc

         foreach ($neffen as $val) { echo $val; }

         foreach ($tmnt as $turtle => $weapon) {
            echo "Name: $turtle\tWeapon: $weapon\n";
         }

         while ($neffen) { echo array_shift($neffen); }
         sizeof($neffen); // 0
?>
  • foreach mit key=>value auch für numerisch indexierte Arrays
  • zudem noch do statement while (condition)

Schleifen

<?php    $tmnt = [
            ['Leonardo',     'blue',   'two swords'],
            ['Michelangelo', 'orange', 'a pair of nunchucks'],
            ['Raphael',      'red',    'a pair of sai'],
            ['Donatello',    'purple', 'a bō staff']
         ];

         foreach ($tmnt as list($turtle, $color, $weapon)) {
            echo "$turtle waers a ${color} bandana and $weapon.\n";
         }
?>
  • list: Weist Variablen zu, als wären sie ein Array

Funktionen

<?php    function multiply($num1, $num2) {
            return $num1 * $num2;
         }

         // Default Parameter
         function greet($name = 'Unbekannter') {
            echo "Hallo $name.";
         }

         greet('Donald'); // Hallo Donald.
         greet();         // Hallo Unbekannter.
?>
  • keine Überladung (overloading) im klassischen Sinne (mit Magie möglich)
  • Typen wieder nicht festgelegt, Hinting möglich
  • Typ vom Rückgabewert ist nicht definiert
  • Es gibt Parameter Defaults
  • Parameter können als Wert oder Referenz übergeben werden
  • Kein Fehler, wenn Funktionen mit zu vielen Parametern aufgerufen werden (aber bei zu wenig)
  • Funktionen müssen immer mit Klammern aufgerufen werden (echo und so sind Ausnahmen, weil eigene Sprachkonstrukte und keine Funktionen)
  • Können nicht undefiniert oder redefiniert werden

Funktionen

<?php    function nimmersatt($a, $b) {
            $params = implode(', ', func_get_args());
            echo "Parameter: $params.\n";
         }
         // Variadische Funktionen
         function nimmersatt2($a, $b, ...$params) {
            echo 'Anzahl weiterer Parameter: ' . count($params);
         }
         $neffen = array('Tick', 'Trick', 'Track');
         nimmersatt2('foo', ...$neffen); // 2 // Argument Unpacking
?>
  • variadische Funktion: Funktion unbestimmter Arität (Parameteranzahl nicht bereits zur Deklaration festgelegt)

Funktionen

<?php    // Type Hinting
         function size(Array $array) {
            return sizeof($array);
         }

         echo size(array(1,2,3)); // 3
         echo size('nooooooooo'); // PHP Catchable fatal error …

         // Return Type Declarations
         function foo() : array {
            return [];
         }
?>

Rekursion

<?php
         function factorial($number) {
            if (!$number) return 1; // 0 == false
            return $number * factorial($number - 1);
         }

         echo factorial(6); // 720
?>

Referenzen

<?php    $val = 5;
         function square1($number) { return $number * $number; }
         echo square1($val); // 25

         // Objekt-Referenzen durch &-Operator
         function square2(&$number) { $number = $number * $number; }
         square2($val);
         echo $val; // 25

         square2(11); // PHP Fatal error:
                      // Only variables can be passed by reference
?>
  • default ist value passing und durch lazy-krams (copy on write) ist das auch schnell genug, darum lieber so

Pointers / Variable Variables

<?php    $zahl = 5;
         $name = 'zahl';
         $$name = 3;
         echo $zahl; // 3

         $woot = 'name';
         $$$woot = 7;
         echo $zahl; // 7

         ${'za' . 'hl'} = 11; // $zahl = 11;
?>

Callbacks

<?php
   function yell() { echo 'Yeah!'; }

   function waitand($callback) {
      sleep(2);
      // $callback(); // tollkühner, geht aber auch
      is_callable($callback) && call_user_func($callback);
   }

   waitand('yell'); // nach 2 Sekunden: "Yeah!"
?>

Callbacks

<?php
   function length($a, $b) {
      return strlen($a) - strlen($b);
   }

   $tiere = array('Hund', 'Katze', 'Wal', 'Stirnlappenbasilisk');

   uasort($tiere, 'length'); // Wal, Hund, Katze, Stirnlappenbasilisk
?>

Anonyme Funktionen

A.k.a. Closures, Funktions-Literale, Lambda-Funktionen.

<?php
   uasort($tiere, function ($a,$b) {
      return strlen($a) - strlen($b);
   });

   $greet = function($name) { echo "Hallo $name\n"; };
   $greet('World');
   $greet('PHP');
?>

Modules

  • Keine entsprechenden Strukturen, aber require und include (*_once)
  • Quasi Kopiervorgang
  • Kann überall verwendet werden

zahlen.php

<?php
   $zahlen = array(1,2,3);
?>

index.php

<?php
   require_once 'zahlen.php';
   echo array_sum($zahlen); // 6
?>
  • Urpsprünglich: Auslagerung von Seitenteilen, z.B. header.php, footer.php etc

Modules

<html>
   <head>
      <title>Home</title>
   </head>
   <body>
      <?php include header.php ?>
      … Content …
   </body>
</html>

Debugging

Web

Superglobals

$GLOBALS Alle Variablen im globalen Gültigkeitsbereich
$_GET GET-Variablen
$_POST POST-Variablen
$_COOKIE Cookies
$_REQUEST Zusammenfassung aus $_GET, $_POST und $_COOKIE
$_FILES Dateiupload-Variablen (hochgeladene Dateien)
$_SERVER Informationen über Server
$_SESSION Session-Variablen
$_ENV Umgebungsvariablen
  • Immer und überall verfügbar
  • Alles Arrays
  • Formulare übergeben immer Strings (kein int, bool o.ä.)
  • Früher auch $HTTP_COOKIE_VARS, $HTTP_GET_VARS und $HTTP_POST_VARS – nicht verwenden!
  • gibt noch weitere (bspw. für Shell-Scripte), aber hier nicht relevant

$_SERVER

Superglobale Variable, die alle Informationen über den Webserver enthält.

REQUEST_METHOD HTTP-Requestmethode
DOCUMENT_ROOT Document Root-Verzeichnis
SCRIPT_FILENAME Pfad des aktuell ausgeführten Skripts
HTTP_USER_AGENT Formulardaten
HTTP_REFERER Angebliche Web-Herkunft des Besuchers
REMOTE_ADDR IP des Besuchers

$_SERVER

<?php

   if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE ||
       strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== FALSE) {

       echo "Sie benutzen Microsofts Internet Explorer.<br />";

   }

?>

Filter

<?php    $url = filter_var($_POST['url'], FILTER_SANITIZE_URL);
         $safe_html = htmlentities($input, ENT_QUOTES, 'UTF-8'); ?>
  • Wenn jemand fremdes an Ihrer Tür steht und Ihnen Essen anbietet – würden Sie es essen?
  • Regel #2: Data must be validated as it crosses the boundary between untrusted and trusted environments.
  • Validate: boolean, email, float, int, ip, regex, url
  • Sanitize:
  • Flags: strip low, strip high, allow fraction, allow thousand, IPv4, IPv6,

HTTP

header() Sendet einen HTTP-Header in Rohform
headers_list() Liste der gesendeten / zu sendenden Header
headers_sent() Prüft, ob oder wo die Header bereits gesendet wurden
setcookie() Sendet ein Cookie
setrawcookie() Sendet ein Cookie, ohne seinen Wert zu URL-kodieren
  • Header und Cookies müssen vor jeglichem Inhalt kommen

Cookies

<?php
   $value = 'irgendetwas von irgendwo';
   setcookie('TestCookie', $value);
   setcookie('TestCookie', $value, time() + 3600);  /* verfällt in 1 Stunde */
   setcookie('TestCookie', $value, time() + 3600, '/~rasmus/', '.example.com', 1);
?>
<?php echo $_COOKIE['TestCookie']; ?>
  • Parameter
    • name: Der Name des Cookies, einziger obligatorischer Parameter
    • value, expire, path, domain, secure, httponly

Sessions

Möglichkeit, mit Client assoziierte Daten serverseitig zu speichern.

<?php    session_start();
         $_SESSION['guthaben'] = 1000000;
?> … nächste Anfrage …
<?php    session_start();
         echo $_SESSION['guthaben'];
         session_destroy();
?>