Post on 04-Feb-2016
description
Server side scripting
1WebtechnologieLennartHerlaar
Inhoud
• PHP
• Meer PHP
• En nog meer PHP
• Arrays beelden keys op values af• Ook als de indices integers zijn• Pas op met aannames m.b.t. de volgorde
• Veel array functies• in_array, array_search, array_merge,
array_reverse, array_flip, array_pop, array_push, array_map, ...
Associative arrays
$myarray = array(1 => "Dog", "Cat", "Scary" => "Bat");$myarray2 = array(0, 2 => 5, 3);$myarray[0] = "Rat";print_r($myarray);
array_keys($myarray); // (1, 2, "Scary", 0)array_values($myarray); // ("Dog", "Cat", "Bat", "Rat")count($myarray); // 4list($a, , $c) = $myarray2; // $a is 0, $c is 5
foreach ($students as $student) { echo("$student\n"); }foreach ($library as $isbn => $title) { echo "Book with ISBN $isbn has title $title\n";} // Volgorde?
Frustrerend?
Sorteren
• Grote hoeveelheid sorteerfuncties• sort(), asort(), arsort(), ksort(), krsort(), rsort(),
usort(), uasort(), uksort(), natsort, ...• Sort is de basis; herordening, integer keys
• r = reversed, a = value, k = key, u = user defined
• a en k laten de associatie intact• nat voor "natuurlijk" sorteren: img2.gif vs.
img12.gif
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana");ksort($fruits); // a => orange, b => banana, d => lemonasort($fruits); // b => banana, d => lemon, a => orangesort($fruits); // 0 => banana, 1 => lemon, 2 => orange
Strings en arrays revisited
$name = "Blob";echo ":$name:"; // :Blob:echo "$nameje"; // lege stringecho "{$name}je"; // Blobjeecho "\{$name\}"; // \{Blob\}$a[2][3] = $name;echo "De {$a[2][3]}!"; // De Blob!echo "De " . $a[2][3] . "!"; // De Blob!echo "En niet de $a[2][3]!"; // En niet de Array[3]!
$words = explode(" ","Jack in the box"); // Array!$str = implode("-", $words); // Jack-in-the-boxstrtr($posting, array("ROTFLMAO" => "rolling on the floor...", ...));strtr($posting, "äåö", "aao");
• Daar gaan we weer...
Type juggling en casting
$myFirstVar = 42;$myFirstVar = 'We are sorry for the inconvenience';
$x = 1 + true;$x = NULL + false;$x = (bool)0;$x = (bool)0.0;$x = (bool)"";$x = (bool)"0";$x = (bool)"0.0";$x = ("0" == true);$x = (true == "false");$x = ("1" == 1);$x = ("1" === 1);
var_dump($x);var_export($x);
$x = "the answer is " . "42";$x = 3 . "5";$x = "the answer is " + "42";$x = 3 + "5";$x = 3 * "5";$x = "this is " + true;
Vergelijk dit met JavaScript...
$x = array_search($myval, $myarray);
Server side scripting
8WebtechnologieLennartHerlaar
En nog meer PHP
Class based
• Object model herschreven voor PHP5, deels 5.3• Breuk met PHP4; incompatible legacy code
• Objects en classes• Een object heeft functies en variabelen
• Methods en properties• Methods en properties kunnen dynamisch
aan objecten toegevoegd worden• Een object is een instantiatie van een
class• Een class is een blauwdruk voor een object
• De classes vormen een hiërarchie
Vergelijk dit met JavaScript...
Objecten
class Cart { private $items; // Pas op!
public function add_item ($artnr, $num) { $this->items[$artnr] += $num; }
public function remove_item ($artnr, $num) { if ($this->items[$artnr] >= $num) { $this->items[$artnr] -= $num; return true; } else { return false; } }}
$cart = new Cart;$cart->add_item(1, 1);$cart->add_item("42", 42);$another_cart = new Cart;$another_cart->add_item("0815", 3);
Public, private, protected
Object dynamics
• Naast object dynamics ook class dynamics• Lastiger dan prototype dynamics in
JavaScript• Probeer dit allemaal niet nodig te
hebben...
$cart1 = new Cart;$cart2 = new Cart;$cart2->add_item("a",10);$cart2->add_item("b",5);
$cart1->val = "cart1";echo ($cart1->val); // cart1echo ($cart2->val); // Niets
echo implode(";",$cart2->items); // 10;5unset ($cart2->items);echo ($cart2->items); // Niets
Class inheritance
• Geen multiple inheritance• Wel multiple interfaces
class Named_Cart extends Cart { private $owner; function set_owner($name) { $this->owner = $name; }
function get_owner() { return($this->owner); }}
Constructors
• Magic Method met de naam __construct• Constructor van super class moet
expliciet aangeroepen worden• Eveneens een destructor beschikbaar
class Constructor_Cart extends Cart { function __construct($item = "a", $num = 1) { $parent::__construct(); $this->add_item ($item, $num); }}
$default_cart = new Constructor_Cart;$different_cart = new Constructor_Cart("b", 17);
Paamayim Nekudotayim
• Dubbele dubbele punt
• Scope resolution operator
• Static properties en methods
• Geen instantiatie nodig
• Overridden methods
• Methods van super classes
• Class constants
class Foo { public static function myStaticFunc() { [...] }}
Foo::myStaticFunc();
class OtherClass extends MyClass { public function myFunc() { [...] parent::myFunc(); }}
Functies op objecten
function print_vars($obj) { $vars = get_object_vars($obj); foreach ($vars as $prop => $val) { echo "$prop = $val\n"; }}
function print_methods($obj) { $methods = get_class_methods(get_class($obj)); foreach ($methods as $method) { echo "function $method()\n"; }}
Zwak getypeerd, dynamisch
• Niet nodig variabelen of properties te declareren
• Type wordt "at runtime" bepaald, duck typing
• Automatische type conversion• Functies zijn in de regel geen 1st class
citizens• Functies en properties kunnen dynamisch
aan objecten toegevoegd worden (maar…)• Functies met mogelijk variabel aantal
parameters• Polymorfie• Nesting van functiedefinities, closures
(PHP5.3)
Vergelijk dit met JavaScript...
Centraal architectuur diagram
WebserverWebbrowser
RDBMSStatische
files
Form, parameters
HTML
HTM
L+
cod
e
SQ
L
Parameters, code
HTML
File a
ccess
Resu
lt s
et
Interpreterof compiler
Superglobals
• PHP kent een aantal bijzondere variabelen• Superglobals: automatisch beschikbaar in elke
scope
• Arrays met (veelal) informatie over de buitenwereld
• $_SERVER: server en execution environment
• $_GET: key / value paren uit de GET query string
• $_POST: key / value paren uit de POST body
• Ook: $_FILES, $_COOKIE, $_SESSION, $_ENV
• $_REQUEST = $_GET + $_POST + $_COOKIE
Superglobals
<?php echo $_SERVER["SERVER_NAME"] . "<br/>"; echo $_SERVER["SERVER_ADDR"] . "<br/>"; echo $_SERVER["SERVER_PORT"] . "<br/>"; echo $_SERVER["REQUEST_TIME"] . "<br/>"; echo $_SERVER["REQUEST_METHOD"] . "<br/>"; echo $_SERVER["REQUEST_URI"] . "<br/>"; echo $_SERVER["HTTPS"] . "<br/>"; echo $_SERVER["HTTP_USER_AGENT"] . "<br/>"; echo $_SERVER["REMOTE_ADDR"] . "<br/>"; echo $_SERVER["REMOTE_PORT"] . "<br/>";?>
Form processing
<form name="input" action="welcome.php" method="get"> First name: <input type="text" name="first"/><br/> Last name: <input type="text" name="last"/><br/> <input type="submit" value="Send"/></form>
<?php echo $_GET["first"]; // Geen URL decoding nodig echo $_REQUEST["first"];
extract($_GET, EXTR_PREFIX_ALL, "imported") // Pas op! echo $imported_first;
// Old-skool echo $HTTP_GET_VARS["first"];
// Met PHP directive register_globals = on echo $first; // Pas op! (Old skool; < PHP 5.4)?>
http://…/welcome.php?first=Willie&last=Wartaal
Odds & ends
• Includen van PHP code• include() en require()• Local / remote, scoping• Let op: HTML-context! Gebruik <?php ?>
• Aanpassen PHP settings• Vele tientallen setting• In de config file, maar soms ook "at runtime"• ini_set('display_errors', 1),
ini_get('post_max_size')• Genereren van HTTP headers
• header(), maar pas op met whitespace...
<?php// We serveren een PDF uit...header('Content-type: application/pdf');
// ...en we noemen 'm doc.pdfheader('Content-Disposition: attachment; filename="doc.pdf"');[...]?>
• Heel veel functies in de core...• ...en heel veel functies in extensions
• Compressie, cryptografie, cookies, beeldverwerking, e-mail, XML, file system, datum/tijd, sessions, URIs, FTP, databases, mathematische bewerkingen, TCP, sockets, HTTP, SOAP, JSON, LDAP, PDF, MIME, ...
• We komen er nog een aantal van tegen• State, sessions, databases, security, stateful
web• Belang van frameworks
Odds & ends
PEAR PECL
• phpinfo()
PHP configuratie
State, sessions, databases
24WebtechnologieLennartHerlaar
Inhoud
• State
• Cookies en sessions
• Webdatabases
• Databases en PHP
• (Transactions)
State
• HTTP revisited• HTTP is stateless• HTTP kent page based requests
• In de regel geen continu draaiende applicatie• Niet op de server, niet in de client
• Maar we willen wel persistency• State moet ergens opgeslagen worden• In de client, maar dan wel telkens meesturen• In de server, maar dan wel een
identificatieprobleem• Verschillende opties
Hidden input fields
• State wordt "verborgen" in het formulier• Hidden input fields, state opgeslagen in de client
• Bij submit worden deze waarden meegestuurd• Onderdeel van de GET query string / POST
body• En opnieuw verwerkt door het server side
script• Problemen met hidden input fields
• Verwarrend: gebruik back button geeft verlies state
• Inefficiënt: alle state ping-pongt heen en weer• Onveilig: de gebruiker kan eenvoudig bij de
state• Complex: scripten ping-pongen en input
validation
Hidden input fields
<form name="product" action="shop.php" method="get"> Product: <select name="product"> <option value="62629">Volvo</option> <option value="89124">Saab</option> <option value="64625">Fiat</option> <option value="31763">Audi</option> </select><br/> <input type="submit" value="Send"/> <input type="hidden" name="step" value="productinfo"/></form>
<form name="input" action="shop.php" method="get"> Full name: <input type="text" name="name"/><br/> Address: <input type="text" name="address"/><br/> <input type="submit" value="Send"/> <input type="hidden" name="step" value="buyerinfo"/> <input type="hidden" name="product" value="64625"/> <input type="hidden" name="price" value="8995"/></form>
<form name="input" action="shop.php" method="get"> card number: <input type="text" name="cardno"/><br/> card name: <input type="text" name="cardname"/><br/> <input type="submit" value="Send"/> <input type="hidden" name="step" value="paymentinfo"/> <input type="hidden" name="product" value="64625"/> <input type="hidden" name="price" value="8995"/> <input type="hidden" name="name" value="Willie Wartaal"/> <input type="hidden" name="address" value="..."/></form>
<form name="input" action="shop.php" method="get"> card number: <input type="text" name="cardno"/><br/> card name: <input type="text" name="cardname"/><br/> <input type="submit" value="Send"/> <input type="hidden" name="step" value="paymentinfo"/> <input type="hidden" name="product" value="64625"/> <input type="hidden" name="price" value="89"/> <input type="hidden" name="name" value="Willie Wartaal"/> <input type="hidden" name="address" value="..."/></form>
<form name="input" action="shop.php" method="get"> Full name: <input type="text" name="name"/><br/> Address: <input type="text" name="address"/><br/> <input type="submit" value="Send"/> <input type="hidden" name="step" value="buyerinfo"/> <input type="hidden" name="product" value="64625"/> <input type="hidden" name="price" value="8995"/></form>
Hidden input fields
shop.php?[...]step=buyerinfo&product=64625&price=8995shop.php?[...]step=buyerinfo&product=64625&price=89
Hidden input fields
<input type="hidden" name="step" value="buyerinfo"/><input type="hidden" name="product" value="64625"/><input type="hidden" name="price" value="8995"/><input type="hidden" name="checksum" value="7ce9e97f43808be0d23f0493c3e1345b"/>
md5("step=buyerinfo&product=64625&price=8995")
md5("step=buyerinfo&product=64625&price=8995MyLittleSecret")
md5("step=buyerinfo&product=64625&price=89")
6ae40396005969e2c301b5eafa463285
9eece848a4c43a0b1144f863d770c66b
<input type="hidden" name="step" value="buyerinfo"/><input type="hidden" name="product" value="64625"/><input type="hidden" name="price" value="89"/><input type="hidden" name="checksum" value="6ae40396005969e2c301b5eafa463285"/>
<input type="hidden" name="step" value="buyerinfo"/><input type="hidden" name="product" value="64625"/><input type="hidden" name="price" value="89"/><input type="hidden" name="checksum" value="9eece848a4c43a0b1144f863d770c66b"/>
REPLAY!md5("step=buyerinfo&product=64625&price=8995MyLittleSecretTimestamp")
<input type="hidden" name="step" value="buyerinfo"/><input type="hidden" name="product" value="64625"/><input type="hidden" name="price" value="8995"/><input type="hidden" name="ts" value="timestamp"/><input type="hidden" name="checksum" value="b368395508548682751710ccd2548d24"/>
• Feitelijk het opbouwen van state in de
URL• Bij gebruik van GET
• Generiek principe• Alle state aan elke link toevoegen als query
string
• Form action wordt het script met de state tot
nu toe
• Maar pas op...
• Dan wel gebruik maken van POST
• Beter: met hidden input fields en GET of POST
State opbouwen in URL
<form name="input" action="shop.php?step=paymentinfo&[...]&product=64625" method="post"> Full name: <input type="text" name="name"/><br/> Address: <input type="text" name="address"/><br/> <input type="submit" value="Send"/></form>
<a href="specials.html?[...]&step=buyerinfo&product=64625">See special deals</a>
't Heeft allemaal dezelfde problematiek!
State, sessions, databases
32WebtechnologieLennartHerlaar
Cookies en sessions
Cookies
• State wordt als "brokje" data opgeslagen• In de client
• Server geeft client opdracht cookie te zetten
• Client stuurt het cookie mee met elk request• Indien cookie en request matchen
• Uitwisseling op basis van HTTP headers• Server zet het cookie met Set-Cookie
• Cookies zijn key-value paren; associative array
Set-Cookie: product=64625; Max-Age=3600
Cookie: product=64625
Cookies
• Cookies hebben aanvullende attributen• Expires: wanneer het cookie verloopt (ook:
Max-Age)
• Domain: voor welke domeinen het cookie
geldig is
• Path: ...en voor welke URLs binnen het domein
• Secure: of het via HTTPS verzonden moet
worden
• HttpOnly: of het alleen bedoeld is voor HTTP
requests
Set-Cookie: userid=willie; Domain=shop.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnlySet-Cookie: product=64625; Domain=.foo.com; Path=/; Expires=Wed, 04-Mar-2015 14:30:01 GMT;
Cookies in PHP en JavaScript
• PHP ondersteunt op transparante wijze cookies
• Header output eerst, dus cookies ook eerst!
• Cookies zijn vanuit JavaScript bereikbaar• Zowel lezen als schrijven is mogelijk• Alleen indien matchend en geen HttpOnly
document.cookie = 'koekje=hello;expires=Wed, 05 Mar 2014 14:35:01 GMT';
var koekje = document.cookie; // let op: string met key-value paren!
<?php $count = $_COOKIE["count"] + 1; setcookie("count", $count, time()+3600); echo $count;?>
Cookies?
• Soorten cookies• Persistent, Session, Supercookie,
Trackingcookie, ...• Cookies lossen niet alle eerdere
problemen op• Inefficiënt, onveilig
• Daarnaast nieuwe specifieke problemen• Cookies kunnen in de browser geweigerd
worden• Beperkingen m.b.t. aantal en omvang van
cookies• Cookies hebben een matige reputatie• Wettelijke beperkingen aan het gebruik van
cookies• Cookies soms ten onrechte geweigerd