33
Mis asi see on? PHP on server-poolne HTML-i lisatud script keel. Lühend PHP on tegelikult rekursiivne, tähistades väljendit PHP Hypertext Preprocessor (PHP hüperteksti-eeltöötleja; siin PHP tuleb omakorda samadest sõnadest jne). Alternatiivne tõlgendus pakub PHP Hypertext Preprocessor-lause PHP tähenduseks PHP eelkäija Personal Home Page (tegelikult lisandus siia veel sõna Tools) lühendit. PHP on HTML-i lisatud (embedded) serveripõhine (erinevalt brauseripõhisest keelest nagu Javascript) skriptikeel. Enamus keele koostisosadest on laenatud mujalt (C, Java, Perl), kuid on ka ainult PHP-le omaseid käske. Keele eesmärgiks on kiirelt ja dünaamiliselt genereeritavate veebilehtede loomine. PHP käsud lisatakse harilikule HTML-veebilehele eraldi PHP-märgenditena, mis võivad paikneda ükskõik kus veebilehe tekstis. Selles mõttes on ta Javacripti sugulane (PHP käskude üks esituskuju sarnaneb Javascripti esitusega), kuid kui Javascripti käsk pannakse tööle lugeja enda arvutis (veebilehitsejas ehk brauseris), siis PHP käsk täidetakse veebiserveris ja brauserisse saadetakse vaid lõpptulemus (sarnaselt CGI-programmidega). PHP jooksutamiseks on vaja PHP serverit. Niisama kirjutan- koodi ja vaatan-brauseris põhimõttel asi ei tööta. Fail tuleb uploadida serverisse(nagu nt zone.ee) ja siis sealt brauseriga vaadata. Mida me PHP-s teha saame? Peaaegu kõike, mida teistes CGI programmides, näiteks koguda infot, genereerida dünaamilisi (kasutaja tegevusele vastavalt muutuvaid) veebilehti, saata või vastu võtta "präänikuid" (cookie; veebiserveri poolt kasutaja arvutisse salvestatav väike andmekogum, mida harilikult kasutatakse lehe olekute meeldejätmiseks - näiteks veebikaupluse ostukorvides). 1

PHP tutvustus

  • Upload
    byte

  • View
    380

  • Download
    11

Embed Size (px)

DESCRIPTION

Autor: Toomas Ilistom

Citation preview

Page 1: PHP tutvustus

Mis asi see on?

PHP on server-poolne HTML-i lisatud script keel.

Lühend PHP on tegelikult rekursiivne, tähistades väljendit PHP Hypertext Preprocessor (PHP hüperteksti-eeltöötleja; siin PHP tuleb omakorda samadest sõnadest jne). Alternatiivne tõlgendus pakub PHP Hypertext Preprocessor-lause PHP tähenduseks PHP eelkäija Personal Home Page (tegelikult lisandus siia veel sõna Tools) lühendit.

PHP on HTML-i lisatud (embedded) serveripõhine (erinevalt brauseripõhisest keelest nagu Javascript) skriptikeel. Enamus keele koostisosadest on laenatud mujalt (C, Java, Perl), kuid on ka ainult PHP-le omaseid käske. Keele eesmärgiks on kiirelt ja dünaamiliselt genereeritavate veebilehtede loomine.

PHP käsud lisatakse harilikule HTML-veebilehele eraldi PHP-märgenditena, mis võivad paikneda ükskõik kus veebilehe tekstis. Selles mõttes on ta Javacripti sugulane (PHP käskude üks esituskuju sarnaneb Javascripti esitusega), kuid kui Javascripti käsk pannakse tööle lugeja enda arvutis (veebilehitsejas ehk brauseris), siis PHP käsk täidetakse veebiserveris ja brauserisse saadetakse vaid lõpptulemus (sarnaselt CGI-programmidega).

PHP jooksutamiseks on vaja PHP serverit. Niisama kirjutan-koodi ja vaatan-brauseris põhimõttel asi ei tööta. Fail tuleb uploadida serverisse(nagu nt zone.ee) ja siis sealt brauseriga vaadata.

Mida me PHP-s teha saame? Peaaegu kõike, mida teistes CGI programmides, näiteks koguda infot, genereerida dünaamilisi (kasutaja tegevusele vastavalt muutuvaid) veebilehti, saata või vastu võtta "präänikuid" (cookie; veebiserveri poolt kasutaja arvutisse salvestatav väike andmekogum, mida harilikult kasutatakse lehe olekute meeldejätmiseks - näiteks veebikaupluse ostukorvides).

PHP suurimaks plussiks aga peetakse võimalust kirjutada väga kiirelt ja lihtsalt andmebaasiga seotud veebilehti. PHP toetab paljusid andmebaase, tuntumatest võib mainida dBase, MySQL, Oracle, Informix, InterBase jne. Ka oskab PHP suhelda selliste protokollidega nagu IMAP, SNMP, NNTP, POP3 või HTTP.

PHP-faili laiendiks on kas

.php vastavalt PHP versioonile .php3 või .php4 phtml (mõned serverid)

Veidi ajaloost

PHP sai alguse aastal 1994 Rasmus Lerdorfi Perl-keele häkkimisest - algset varianti kasutas ta oma kodulehe jälgimiseks. Esimene versioon oli tuntud Personal Home

1

Page 2: PHP tutvustus

Page Tools-i nime all. See sisaldas väga lihtsat käsuprotsessorit ehk mootorit (parser), mis sai aru mõnest spetsiaalsest makrost ning töötas külalisteraamatu ja loendurina. Mootor kirjutati 1995, aasta keskel ümber ja sai tuntuks kui PHP/FI versioon 2. FI nimetus tuleneb Form Interpreter-i nimelisest lisapaketist, mille Rasmus kirjutas HTML-i jaoks. Kombineerides Personal Home Page Tools-i Form Interpreter-iga ja lisades mSQL-i toetuse oligi tulemuseks PHP/FI.

1997. aasta keskel tehti süsteemis uuendusi ja palju asju kirjutati täelikult uuesti. Nii sündiski PHP versioon 3 (PHP3) - praegugi laialt kasutatav PHP standard.

Tänaseks kautab PHP-d juba üle miljoni veebilehe. Viimaseks standardiks on PHP versioon 4, mis kasutab võimsat Zendi skriptimismootorit. Sellega on kasvanud PHP töötamise kiirus. Enamasti kasutatakse PHP-d Apache'i veebiserveris, kuid pidevalt laieneb ka teiste veebiserverite toetus. PHP töötab nii Windowsi kui Unixi ja Linuxi keskkonnas.

Kuidas PHP töötabPHP lehed on koostatud kolmest osast: tekst, PHP scriptid, ja HTML. Web´ilehed, mis sisaldavad PHP scripti, on laiendiga .php. Kui klient saadab päringu mõnele sellisele lehele, saadab server veebilehe läbi PHP scripti mootori tõlgendamiseks. See on põhiline erinevus PHP ja teiste script keelte vahel. PHP´d tõlgendatakse serveri mitte brauseri kaudu. Server konverteerib PHP scripti HTML keelde, ja võib hõlpsasti kohandada lehte vastavalt kasutaja vajadustele.

2

Page 3: PHP tutvustus

Andmetüübid

PHP toetab järgmisi andmetüüpe:

murdarvud (double) N: 1.234; 1.2e3 täisarvud (integer) N: 1234; -1234 tekstiväärtused (string) N: "Tere", "1. september" loogikaväärtused (bool; alates PHP4-st) massiivid objektid

Tekstiväärtused:

Nagu MySQLi puhul, kasutatakse ka PHP-s juhtsümboleid ehk eritähendusega tekstiväärtusi. Mõned olulisemad:

"\n" - uus rida "\t" - tabulatsioon (horizontal tab) "\\" - kurakaldkriips (backslash) "\$" - dollarimärk "\"" - jutumärk

PHP skript

PHP skripti moodustavad käsud kirjutatakse <? ja ?> märkide abil otse HTML faili, kusjuures faili nime lõpus peab olema .php. Näiteks sellise sisuga fail php.php

<html><body><h1><? echo "Tere päevast!"; ?></h1><p><? /* see on kommentaar mida PHP mootor ignoreerib */echo "Mina olen PHP skritp."; ?></p></body></html>

on samaväärne HTML-tekstiga

<html><body>

3

Page 4: PHP tutvustus

<h1>Tere päevast!</h1><p>Mina olen PHP skritp.</p></body></html>

Ekraanile kuvatakse tekst

"Tere päevast!Mina olen PHP skript."

Veebiserver asendab <? ja ?> märkide vahel asuva PHP käskude väljundiga, antud juhul tekstiga.

Üldiselt peavad PHP käsud lõppema semikooloniga (;) nagu

echo "Tere päevast!";

kuid kui viimase käsu puhul võib semikooloni kirjutamata jätta, näiteks

echo "Mina olen PHP skritp." ?>

PHP skripti sisse saab kirjutada kommentaare eristades nad sarnaselt C keele traditsioonile /* ja */ märkidega muust tekstist

/* see on kommentaar mida PHP mootor ignoreerib */

Samuti kommenteerib '//' välja järgneva teksti kuni rea lõpuni

echo "Tere Priit"; // siin trükitakse välja tekst "Tere Priit"

Include

<? include "tere.html";?>

<body><h1>Tere</h1></body>

Muutujad ja väärtuse omistamine

PHP skriptis saab kasutada arvulist ja tekstist tüüpi muutujaid, samuti massiive ning teha nendega tehteid. Muutujat nime märgitakse alustades dollariga ($), millele järgneb alakriips või tähemärk (a-z, A-Z) ning seejärel võib nimes sisalduda ka numbreid (0-9). PHP eristab väikesi ja suuri tähti. Näiteks on korrektne muutuja nime märkida selliselt

4

Page 5: PHP tutvustus

$kordaja_1

Muutuja tüüpi ei pea enne kasutamist defineerima, piisab muutujale väärtuse omistamisest, mida tehakse võrdusmärgi abil. Näiteks omistame muutujaile väärtused ja teeme mõne tehte

<?$a = -15.5; $b= 20;$c = $a + $b;?><?echo "$a liita $b on $c";?>

Negatiivset arvu peab alustama -märgiga ning pealekomakohti eraldatakse ennekomakohtadest punktiga.

Pange tähele, et <? ja ?> märkide vahel kasutatud muutujad omavad endisi väärtusi ka siis, kui neid hiljem uuesti kasutada mõnes järgmises samas dokumendis asuvas <? ja ?> märkide vahel olevas PHP skriptis.

<?$d = "muinas";$e = "jutt";$f = $d.$e;echo "sõnasid $d ja $e saab kokku ühendada, tulemuseks on $f";?>

Sõnedega (ingl. k. string) tegelemisel on põhiliseks tehteks nende sobivas järjekorras kokkuühendamine. Allpool näitame kuidas sõne osadeks lahutada jms.

Omistamisel saab kasutada

$a = 5;$a = $a + 4;

asemel samaväärset kuid lühemat kirjaviisi

$a = 5;$a += 4;

Muutujale saab omistada operatsioonisüsteemi käsu väljundit kasutades graaviseid. Käsk antakse kasutaja httpd õigustes. Näiteks omistame muutujale $aeg väärtuseks süsteemi aja

$aeg=`date`;

5

Page 6: PHP tutvustus

Sel moel saab kasutaja anda käske, mida ta enda õigustes teha ei saaks. Kasutaja ei tohi veebi välja panna skripte, mille käivitame kahjustaks veebiserverit.

Aritmeetilised tehted

Aritmeetilisi tehteid

"+, -" - liitmine ja lahtutamine "*, /, %" - korrutamine, jagamine ja jääk

tehakse arvväärtustega. Näiteks

<?$a = 3.5;$b = 2;$korrutis = $a * $b;echo "$a ja $b korrutis on $korrutis";?>

Kui arvus kasutada täisarvu ja komakohtadega arvu, siis tulemus sisaldab samuti komakohti.

Juhtstruktuurid

Skripti käigu suunamiseks kasutatakse juhtstruktuure, mis valivad järneva tegevuse vastavalt seatud tingimustele. Tingimusi esitatakse võrdlustehete <,>, <=, >=, ==, != abil. Võrdlustehete tulemusi (tõene, väär) saab omakorda kombineerida loogiliste tehete (and, or, xor, ! $a - not $a) abil.

Loogalisi sulge ({, }) kasutatakse käskude grupeerimiseks plokiks, mis täitetakse või täidetakse korduvalt.

if

if konstruktsiooni abil saab valida kahe võimaliku tegevuse vahel sõltuvalt tingimuse täidetusest.

if (võrdluslause)    {teeme seda} elseif    {teeme teist} else    {teeme kolmandat}

Võrdleme kahte arvu omavahel

if ($a > $b)

6

Page 7: PHP tutvustus

print "a is bigger than b";

$a = 5; $b = 6;if ($a > $b) { print "$a on suurem kui $b";} else { print "$a on väiksem või võrdne $b-ga";}

Asja dünaamilisemaks tehes:

Kasutame funktsiooni date, millel on hirmus palju parameetreid, meie kasutame nendest ainult "H"'i, mis näitab käesolevat tundi kahekümne nelja tunni süsteemis.

date("H")

Juhul, kui kell on näiteks 14.45 on date("H"); väärtus 14

<?php$lause1="Teretulemast minu kodukale, ilus päev täna!";$lause2="Teretulemast minu kodukale, ööloom sihuke :)";

if (8<=date("H") && 21>=date("H"))    echo $lause1; //ütleme esimese lauseelse    echo $lause2; //ütleme teise lause?>

Igaks juhuks vaatame veel üle if’i süntaksi:

if (8<=date("H") && 21>=date("H"))

Seda loeme niimoodi: kui 8 on väiksem või võrdne kui pregune tund JA 21 on suurem või võrdne kui preagune tund, siis on if-lause tõene.

for

for ($i = 1; $i <= 10; $i++) { print $i; }

for-konstruktsiooni abil saab täita sama plokki käske kontrollitud arv kordi kuni tinigimus on tõene. Näiteks kirjutab skript ekraanile arvud ühest viieni

7

Page 8: PHP tutvustus

for ($i = 1; $i < 6; $i++){echo "$i";}

$i=$i++ on samaväärne nagu $i=$i+1.

Sama tulemuse väljastab ka selline skript

$i = 1;for (;;) { if ($i > 5) { break; } print $i; $i++;}

for (;;) vastab lõpmatule kordusele kusjuures break annab käsu tulla kordusest välja.

while

While konstruktiooni puhul täidetakse plokki seni kuni tinigimus on tõene. Trükime arvud ühest kümneni välja ka while'i abil

$i = 1; while ($i <= 10) { print $i++; }

$i = 1; while ($i <= 10): print $i; $i++; endwhile;

do ... while

do ... while konstruktsioon on sarnane while'ga erinedes selle poolest, et tingimust kontrollitakse peale ploki täitmist. Seega täidetakse plokki vähemalt üks kord. Näiteks trükime välja arvud ühest viieni

$i = 5;do { print $i;

8

Page 9: PHP tutvustus

} while ($i>0);

foreach

foreach - konstruktsioon võimaldab mugavalt täita plokis olevaid lauseid iga massiivi elemendi jaoks. Näiteks väärtustame viie-elemendiline massiivi $m ning trükime selle elemendid välja

$m = array ("Jaan", "Peeter", "Marta", "Laura");$i=1;foreach ($m as $element) { print $i++.". $element";}

Mis näev välja lõplikult nii: 1. Jaan 2. Peeter 3. Marta 4. Laura

Trükkimine

Teksti ja muutujate väärtuste ekraanile trükkimiseks kasutatakse käske echo, print ja printf. Käsud echo ja print on praktiliselt sarnased, väljatrükitav tekst tuleb kirjutada nende järele jutumärkide (") vahele. Näiteks trükib skript välja teksti, muutuja nimed ja nende väärtused

$a = "Mari";$b = 5;$c = -2;$korrutis = $b * $c;echo "$b korda $c on võrdne $korrutis";print "";print "\$a = $a";

Tulemus: 5 korda -2 on võrdne -10 $a = Mari

echo või print argumendiks olev tekst võib ulatud üle mitme rea tinigmusel, et viimase lõpus on semikoolon (;). Soovides trükkida muutuja väärtuse asemel tema nime, tuleb põgeda $ tagurpidi kladkriipsuga (\) nagu \$a.

Kasutades jutumärkide asemel ülakomasid ei asendata muutujaid nende väärtustega

$b = 5;$c = -2;$korrutis = $b * $c;echo '$b korda $b on $korrutis';

9

Page 10: PHP tutvustus

Tulemus: $b korda $b on $korrutis

Soovides formateerida väljundit paindlikumalt tuleb kasutada käsku printf, mille süntaks on sarnane C vastavale käsule. Näiteks teeme arvutused ja trükime välja muutujate väärtused kahe pealekomakohaga

$b = 1.3;print "<pre>";while ($b < 5){printf ("%3.2f%6.2f\n", $b, $b*$b++);}print "</pre>";

%6.2f tähendab, et trükkimisel tuleb korrutisele $b*$b++ vastav väli hoida vähemalt kuue positsiooni laiune, millest kaks on pealekomakohad. Vaikimisi täidetakse tühjad kohad tühikutega ja joondatakse paremale poole so tühikud sisestatakse väärtusest vasemale. Siin on asjakohane kasutada HTMLi pre-tagi, sest muidu "sööb" brauser tühikud ära. Tulemus

1.30 1.69 2.30 5.29 3.30 10.89 4.30 18.49

Funktsiooni defineerimine

Kasutaja saab ise lisaks olemasolevatele funktsioone juurde meisterdada. Näiteks tekitame funktsiooni korruta(), mis vajab kahte arvulist argumenti, korrutab need omavahel ning tagastab tulemuse.

$a = 2; $b = 3;$tulemus = korruta($a, $b);print "$a * $b on võrdne $tulemus";

function korruta ($a, $b) { $korrutis = $a * $b; $a = 10; $b = 15; return $korrutis;}

Tulemus: 2 * 3 on võrdne 6

10

Page 11: PHP tutvustus

Vaikimise antakse funktsioonile üle muutuja väärtus, nagu näites. St kuigi funktsiooni sees defineeritakse $a ja $b väärtused ümber ei mõjuta see skripti muutujate $a ja $b väärtusi. Need on siseliselt erinevad muutujad kuigi samade nimedega.

Soovides, aga funktsiooni seest muuta skripti muutujaid tuleb anda funktsioonile üle muutuja viide. Selleks kirjutatake muutuja nime ette ampersand (&)

$a = 2; $b = 3;$tulemus = korruta(&$a, &$b);print "$a * $b on võrdne $tulemus";

function korruta ($a, $b) { $korrutis = $a * $b; $a = 10; $b = 15; return $korrutis;}

Tulemus: 10 * 15 on võrdne 6

Üldiselt peetakse puhtamaks stiiliks, kui funktsioon ei muuda skripti muutujaid, sest nii on teinekord keerukas võimalikke vigu leida.

Operatsioonid sõnadega

PHP pakub vahendeid tegeleda sõnedega (ingl. k. string). Näiteks ühendame kokku kaks sõnat omistades tulemuse muutujale $koos

$a = "Tere,";$b = " mina siin";$koos = $a.$b;echo $koos;

Kasuga strlen saab leida sõna pikkuse tähemärkides

$sone = "Taavet ja Koljat";$pikkus = strlen ($sone);echo $pikkus;

Käsk strstr tagastab sõna, mille väärtuseks on tähemärgid alates leitud sõnast kuni lõpuni, näiteks

$email = 'priit@localhost';$domain = strstr ($email, '@'); print $domain;

11

Page 12: PHP tutvustus

tagastab @localhost

Sõnest eraldab osa käsk substr, näiteks eemaldame kõik peale esimese tähemärgi

$domain = "@zoo.edu.ee";$domaininimi = substr ($domain, 1)

$domaininimi väärtuseks saab zoo.edu.ee.

Tegeldes veebivormidega kasutataks tihti sarnase struktuuriga sõnesid "nimi=Villem&vanus=25&elukoht=Tartu+linn". Käsu parse_str abil on lihtne omistada muutujaile vastavad väärtused

$str = "nimi=Villem &vanus=25&elukoht=Tartu+linn";parse_str($str); echo "$nimi";echo "$vanus";echo "$elukoht";

12

Page 13: PHP tutvustus

Massiiv$paev = array (pühapäev,esmaspäev,teisipäev,kolmapäev,neljapäev,reede,laupäev);

echo $paev[date("w")];

<?$p = array (pühapäev,esmaspäev,teisipäev,kolmapäev,neljapäev,reede,laupäev);

$k = array (jaanuar,veebruar,märts,aprill,mai,juuni,juuli,august,september,oktoober,november,detsember);

$kuupaev = date("j");$aasta = date("Y");$paev = $p[date("w")];

// kuna meie massiivis vastab jaanuarile 0, date("n") funktsioonis// aga 1, siis peame ühe lahutama:$kuu = $k[date("n")-1];

echo"$paev, $kuupaev. $kuu $aasta";?>

Massiivi tüüpi muutujat märgitakse sarnaselt tavalise muutuja nimega, kuid tema kasutamisel peab arvestama, et tegu on massiiviga. Näiteks defineerime massiivi ja trükime välja selle elemendid

$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");$a = current ($mass);do {print "$a";} while ($a = next ($mass));

funktsioon current tagastab massiivi esimese elemendi väärtuse; next järgmise elemendi väärtuse.

Omades sõna

13

Page 14: PHP tutvustus

$sone = "Priit Jaan Memm Kana Ivo";

saab selle teisendada tühikute kohalt massiiviks käsuga split

$mass = split (" +", $sone);

kus " +" on regulaaravaldis. Kui tulevase massiivi elemente eraldaks üks tühiks, võiks kasutada sarnaselt käsku explode.

$sone = "Priit Jaan Memm Kana Ivo";$mass = explode (" ", $sone);

Vastupidiselt, massiivi saab ühendada sõneks käsuga join

$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");$sone = join (":", $sone);

tulemuseks on sõna

Priit:Jaan:Memm:Kana:Ivo

Massiivi üksikute elementide poole saab pörduda indeksi abil, indekseerimine algab nullist. Näikeks trükime üle ühe välja massiivi elementide väärtused

for ($i=0; $i < sizeof ($mass); $i+=2){ print "$i. $mass[$i]";}

Funktsioon sizeof tagastab massiivi elementide arvu ning konstruktsioon $i+=2 suurendab iga kordusega muutuja $i väärtust kahe võrra. Konstruktsioon $mass[$i] abil pöördutakse massiivi $mass $i-nda elemendi poole.

Käsk array_pop tagastab massiivi viimase elemendi väärtuse ja eemaldab ta massiivist

$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");$viimane = array_pop ($mass);

Käsk array_shift tagastab massiivi esimese elemendi väärtuse ning eemaldab ta massiivist; ülejäänud elemendid nihutatakse ühe positsiooni võrra ettepoole

$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");$viimane = array_shift ($mass);

Sarnaselt lisatakse masiivi algusse ja lõppu elemente käskudega array_unshift array_push

14

Page 15: PHP tutvustus

$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");$elementide_uus_arv = array_unshift ($mass, "Laine", "Jaa");$elementide_uus_arv = array_push ($mass, "Leo", "Liina");

Tulemuseks on massiiv ("Laine", "Jaa", "Priit", "Jaan", "Memm", "Kana", "Ivo", "Leo", "Liina") kusjuures mõlemad käsud tagastavad väärtusena uue massiivi elementide arvu.

Switch

Mida switchiga teha saab?

Üks kasutusi on jällegi faili lisamine includega. Näiteks on meil ühel lehel kaks linki: index.php?lemmikloom=koer ja

index.php?lemmikloom=kass

Nüüd saab antud paremeetreid suurepäraselt töödelda switchga, failis index.php on meil skript:

switch($lemmikloom){    case koer:        include("koerapilt.gif");        break;     case kass:        include("kassipilt.gif");        break;     default:        include("minuendapilt.gif");}

Seletame natuke. Misasi on break? Break lõpetab switchi ahela täitmise. Kui me seda ei paneks, leiaks switch küll õige koha, kuid ei lõpetaks tööd ja täidaks ka kõik endast allapoole jäävad tingimused hoolimata sellest, et need tõesed ei ole. Näiteks üleval näites, kui break'e ei oleks ja $lemmikloom=koer, siis lisatakse ka kassipilt ja minuendapilt. Ühesõnaga - Switch lõpetab töö esimese break'i peale või lõppu jõudes.

Kui include'da pilti, siis enne seda tuleks loomulikult saata välja ka vastav header:

$head="Content-type: image/gif";Header($head);

Siia veel niipalju, et pildi lisamiseks tuleb kogu see kood panna eraldi faili. Lihtsam võimalus pilti lisada on asendada koodis 'include' rida:

15

Page 16: PHP tutvustus

echo"<img src="koer.gif">";

Aga viimase case'i asemel on default? Jah, default täidetakse, kui ükski eelnevatest case'dest ei osutunud tõeks (või kui osutus, aga break oli puudu). Default ei ole kohustuslik.

Muidugi võib switchi ka teisteks puhkudeks tarvitada - näiteks soovid, et iga tund ööpäevas oleks sinu lehekülg erineva taustavärviga, siis kirjuta skript:

switch(date("H")){case 10: echo"<body style=\"background: black; color white;\">"; break;case 1: echo"<body style=\"background: green; color: white;\">"; break;default: echo"<body style=\"background: white; color: green;\">";}

PHP ja turvalisus

Tihtipeale kirjutatakse programmi kiirustades: tähtajad lähenevad, tööpäev saab läbi või lihtsalt ei vaevuta muule, kui koodi funktsionaalsusele tähelepanu pöörama. Ning ununevad kaks asja: esimene on koodi optimiseerimine. Selle saab kompenseerida kiirema serveriga. Teine asi on programmi turvalisus - turvaauke ei kompenseeri millegagi, olgu server nii võimas kui tahes. Järgnevalt ongi toodud mõned näpunäited apsakate vältimiseks.

Failide avamine

Failide avamisega PHP's tuleb olla väga ettevaatlik. Ja sellel alal tehakse pahatihti vigu(ka paljud "veebifirmade" tehtud lehed kannatavad selle haiguse all).

Kunagi ei tohi avatava faili nime edasi anda url real muutuja kaudu. Nt url:index.php?f=kala

include($f);

Nõnda võib iga suvaline tegelane vaadata iga suvalist faili, mis sul kuskil kataloogis leidub. Ettevaatlik tasub olla isegi siis, kui defineerid lisaks ka lühendi:

include($f.'.php');

Sest ehk on sul kogemata kuskil fail nimega mysql.php, mis sisaldab nt MySql kasutajanime ja salasõna, mille sattumine võõrastesse kätesse on ebasoovitav.

16

Page 17: PHP tutvustus

Lahendus:Switchi kasutamine:

PHP kood:

switch($f) {     case slash:         include('slash.php');         break;      case dot:         include('dot.php');         break;      default:         include('ava.php'); }

Nõnda saab avada ainult switch tsüklis defineeritud faile.PS! See ei puuduta ainult include()'t, vaid ka require(), fopen() jmt funktsioone.

Ära kasuta skriptide includemiseks mõeldud funktsioone URL'ide avamiseks, kui sa pole 101% kindel, et seda muutujat keegi muuta ei saa.

PHP kood:

<?php include($url); ?>

Tore skriptike on see niikaua, kuni $url='http://www.neti.ee'; või $url='http://www.php.ee';. Aga hoolitse selle eest, et sinna $url muutujasse ei satuks: $url='http://www.pahalane.ee/v2ga_kuri_skript.txt';, mis näituseks otsustab su veebiserveri failidest tühjendada.

MySql ja muutujad

Teine turvaauk, mida esineb ka paljudes, isegi hirmuäratavalt paljudes programmides, on see, et MySqlile söödetakse sisse kontrollimata muutujad.Üks asi, mis on kohustuslik, on mysql käsus jutumärkide kasutamine:

$sql='select * from users where nimi="'.$nimi.'"';

Sest kui nimi juhtub olema kasutaja sisestatav muutuja, siis asi see tal oma nimeks

17

Page 18: PHP tutvustus

kirjutada:

kala or admin=1

Mille tulemuse tekib query:

$sql='select * from users where nimi=kala or admin=1';

Ehk valitakse ka kõik administraatorite andmed ja need siis kasutajale kuvatakse(loodetavasti keegi tänapäeval siiski passworde tekstina ei hoia, selline asi oleks küll lihtne ja mugav, aga mingi imepisike näpukas kuskil hoopis teises skriptiotsas võib selle saatuslikuks turvaauguks muuta). Ja sellisel juhul ei mängi mingit rolli see, kas addslashes() on kasutuses või mitte. Läbi läheb selline auk igal juhul.

Addslashes() on sinu sõber!

Tõsi, tänapäeval on serveri administraatorid, kes vähegi turvalisusest hoolivad, keeranud php konfist peale kõiksugu toredad võimalused kasutaja käest tulnud muutujates igasuguste ohtlike märkide taandamiseks . Nt sa küll kasutad jutumärke, aga kui ohtlikud märgid(nt jutumärgid ise) taandatud ei ole, siis liidame kokku eeltoodud näites kasutatud query ja sellise stringi:

kala" and admin="1

...mis teeb kokku:

$sql='select * from users where nimi="kala" or admin="1"';

(terve tabeli fetchimiseks tuleks kirjutada nt or 1=1)

Simpel, huh? Näituseks insert query korral pole sugugi võimatu välja mõelda, kuidas ennast, juhul kui eksisteerib väli 'admin', administraatoriks muuta. Või kui tõesti ei suuda välja mõelda, siis sisselogimisel võib enda kasutajanimeks seada hoopis: "kala' #", mis passwordi kysimise osa üldse välja kommenteerib..

select * from users where nimi="adminn" # and password="progejaOliLoll"

Aga ma kasutan ju jutumärke ja php.ini on ka niimoodi paika krutitud, et kogu kasutaja käest tulnud info ära töödeldakse!

Järelikult sul ei ole vaja addslashes pärast üldse muretseda ja võid selle funktsiooni ära unustada... oot! Aga siiski, oletame, et sul on query:

$query='insert into users(id, username) values(0, "'.$muutuja.'")';

18

Page 19: PHP tutvustus

...ning

$muutuja='kala" or id="2';

Kõik oleks nagu korras. Asi läheb korralikult läbi, mingit kasutaja poolt sissesuditud "or" klauslit mysql ei täida.

Aga natuke hiljem võtad sa selle sama asja kuskil teises skriptiotsas lahti:

$query='select username from users where id="4"';

ning pahaaimamatult kasutad sealt saadud tulemusi uue query koostamiseks. Loomulikult ei kasuta sa addslashes() funktsiooni, kuna tegu ei ole kasutajalt saadud infoga ning mingit ohtu karta pole. Ja sellel samal põhjusel ei taanda ka PHP neid muutujaid ära.

$query='select * from users where username="'.$q[0][0].'";';

Aga sinu ohutu query ei küsi andmebaasist mitte sinu oodatud:

select * from users where username="mingi ohtutu kasutajanimi";

Vaid kasutajale meelepärase:

select * from users where username="kala" or id="2";

Pahalane sai oma tahtmise, seekord suht süütukese, aga oletame, et tegemist on nüüd hoopis passwordi muutmise skriptiga ning kasutajanimeks ei oleks mitte kala" or id="2, vaid kala" or username="adminni_nimi_siia... Järeldused tehku igaüks ise.

Muutujate tüübid

Kui sul on teada, et muutuja peab olema numbriline, siis alati veendu selles. Üks pluss on see, et sa saad kindel olla muutuja õiges sisus ning teine asi see, et soovi korral saad vale sisu avastamisel alati pahalase andmed logida ning nt kiirelt omale emaili saata.

Kuidas siis muutujatüüpe kindlaks teha?

Näiteks on sul ilus ja kena number(või sa vähemasti arvad, et peab olema) muutujas $id, siis et selles ikka kindel olla, lased ta läbi sellisest masinast:

$id=(int)$id;

Kui tahad määrata ka else klauslit juhuks, kui tegu ei ole õige asjaga(int kasutamine

19

Page 20: PHP tutvustus

tagastab stringi korral '0', mitte ei anna veateadet), siis uuri funktsioone is_int(), is_bool(), is_integer(), is_numeric(), is_string(), is_array(), is_object() ja is_float().

Hoolitse selle eest, et muutujad tuleksid õigest kohast!

Kui muutujad on ette nähtud formist tulema, siis ära kasuta kuju:

$muutuja

vaid

$HTTP_POST_VARS['muutuja']

Kui form postitatakse get meetodiga, siis $HTTP_GET_VARS['muutuja'], täpselt samuti ka kõigi teiste muutujatega:

URLi realt tulnud muutujad on samuti:$HTTP_GET_VARS['muutuja']

sessioonimuutujad:$HTTP_SESSION_VARS['muutuja']

cookiemuutujad:$HTTP_COOKIE_VARS['muutuja']

Kasutades $HTTP_*_VARS perekonda saab koodi ka igale serverile porditavaks(on servereid, kus register_globals on maha keeratud - kood peab ka seal töötama!).

Siiski, tõsine tegija saadab ka $HTTP_POST_VARS muutujad ise, kasvõi lihtlabaselt telneti kaudu. Aga kuna pahategusid sooritavad muuhulgas ka jõnglased, kellel pole(veel) aimu HTTP protokolli töötamisest, ei tasu $HTTP_POST_VARS'i unustada.(PHP 4.1 asendab $HTTP_*_VARS muutujad $_* muutujatega, nt $_POST, $_COOKIE)

Mõttetu muutujate kasutamine.

Kui vaadata suvalise PHP programmi, olgu see siis vabavara või mitte, konfiguratsioonifaili, siis vähemalt 90% tõenäosusega avastad sa sealt suure hulga muutujaid. Muutujaid, mida mitte keegi eales skripti sees ei muuda. Nagu ntx: mysql andmed; vajalikud kataloogid failide lisamiseks; mingid limit'id jms andmed. Aga kui neid muuta ei ole vaja, miks nad siis muutujad on?? Ilmselt seetõttu, et isegi paljud kogenud programmeerijad pole harjunud kasutama konstante. Või isegi ei teata nende olemasolust! Lihne näide neile, kes esimest korda kuulevad. Konstandi defineerimine ja kasutamine:

20

Page 21: PHP tutvustus

PHP kood:

//defineerimine define(KONSTANDINIMI, 'v22rtus'); //kasutamine echo constant(KONSTANDINIMI); //ka lihtsalt echo KONSTANDINIMI; töötab

...kasutades muutujate asemel konstante, ei anna me kellegile võimalust neid pahatahtlikel eesmärkidel üle kirjutada ning jällegi üks sammuke turvalisuse suurendamise suunas tehtud.

eval() funktsioon ei ole sinu sõber...

...kui sa teda hoole ja armastusega ei kasuta. Kuigi kindlasti on olemas olukordi, kus on vaja eval'it kasutada, siis 90% juhtudest, mil teda kasutatakse, on täiesti mõttetud ning sama probleemi saaks ka muudmoodi lahendada. Eriti ohtlik on olukord, kus eval'it kasutatakse koos kasutajalt saadud andmetega. Üks levinuim olukord evali kasutamiseks on ühe muutuja nimetamine teise muutuja väärtuse järgi(ehk muutuja muutuja). Nt on meil muutuja:

$i='kala';

..ja tahame tekitada muutuja $i väärtuse järgi muutuja 'kala', aga me ei saa seda niisama teha, kuna $i väärtus muutub iga kord. Selle asemel, et kasutada eval'it, tuleb lihtsalt kasutada kõige lihtsamaid muutuja muutujaid:

PHP kood:

$$i='v22rtus';

Selle tulemusena saame skripti(juhul, kui $i==kala) muutuja $kala='v22rtus'; Evalit kasutades tuleb seal sees kasutatavad muutujad alati hoolikalt üle kontrollida!Lisaks eval'ile on veel üks programmidegrupp, mille kasutamisse peab suhtuma väga suure ettevaatusega. Need on serveris programmide käivitamiseks mõeldud funktsioonid.

Logimissüsteemid ja salasõnaga kaitstud lehed

Olles eelnevad vead koodist kõrvaldanud, tuleks natukene mõelda ka programmi disainist tulenevatele vigadele, mis ei ole seotud mingi konkreetse koodireaga. Ja kõige tavalisem selline viga ongi kasutajatuvastamissüsteemi vale ülesehitus või valed vahendid selle ehitamiseks.

21

Page 22: PHP tutvustus

Cookie kui andmete hoidja.

Kui te kasutate küpsiseid kasutajatesüsteemi ehitamiseks, siis1) lisage lehele märkus, et seda mõtet ei ole te saanud minu käest :)2) arvestage, et see on kõige ebaturvalisem viis

Miks?

1) Cookie ise on kriitiliste andmete hoidmiseks ebaturvaline2) Pahatihti ehitatakse selline süsteem valesti ülesse:    -kontrollitakse kasutaja sisestatud andmeid ning selle asemel, et igal lehe laadimisel passwordi ja salasõna kontrollida, salvestatakse kasutaja arvutisse cookie nimega 'logged' ja väärtusega '1' või 'logged' vms ning hiljem kontrollitakse ainult selle olemasolu. Samas kuna cookie on kasutaja poolt sinule antud info, siis võib kasutaja, oskuste olemasolul, seda lihtsalt võltsida ja pääseb vaevata sinu kaitstud keskkonda.

Aga cookie'dest märksa mõttekam on kasutada sessioone.1) Nad on turvalisemad2) Mina soovitan neid cookiede asemel :)

Turvalisemad on nad seetõttu, et sessiooni andmeid säilitatakse serveris, kasutaja käes on kõigest sessiooni nimi, mille alusel talle andmeid jagatakse. Kuigi oskusliku programmeerimise korral võib teha ka süsteemi, kus säilitatakse muutujat logged=1, siis mina ise kasutan igakordset kasutajanime ja passwordi võrdlemist andmebaasis oleva info vastu. Miks?

Vajadusel on mul lihtne kasutajat ka poole sessiooni pealt blokeerida. St ma avastan, et ta ei tegele mu lehel viisakate asjadega ja muudan andmebaasis ta passwordi kiiresti ära. Kui oleks ainult muutuja 'logged=1', siis oleks tema minemasaamine veidi tülikam.

Juhul kui koodi on ikkagi sisse libisenud mingisugune apsakas, siis igakordsel kontrollimisel on asi ikkagi turvalisem; näide:

PHP kood:

session_start(); session_register('logged');

Kasutaja keelab sessioonimuutuja edasiandmise serverile ning kirjutab selle hoopis ise URL rea kaudu üle. Abimees selle vastu on $logged=""; või unset($logged); enne sessiooni alustamist.Kui valida näiliselt lihtsam tee, siis peab alati kindel olema, et sellega turvaauku ei põhjustata.

22

Page 23: PHP tutvustus

PHP-koodi asukoht serveris

Esiteks tuleks veenduda, et keegi teine sinu koodile ligi ei pääseks. Koodi nägemine kergendab sellest läbimurdmist tunduvalt, sest siis on teada, mis ees ootab. Selleks on vajalik, et keegi sinu koodi niisama ei näeks: nt hoida skripte kõigile nähtavas kataloogis parsimisele mittekuuluvate failinimedega. Tavaliselt parsitakse ära .php ja .php3 laiendiga failid, aga kuna see sõltub konkreetsest serverist ja selle administraatorist, siis on seda nimekirja võimalik järgmise jaanipäevani jätkata. Üldjuhul laialt kasutatavat laiendit .inc serverid ei parsi.

Aga veelgi kavalam, kui eraldi koodijuppide äraparsimine, oleks nad paigutada kuskile veebist kättesaadavast kataloogist kõrgemale.

Nt kui veebikataloog on /www/apache/user/htdocs/, siis oleks tore lisatavad php failid paigutada nt kataloogi /www/apache/user/phpfailid/. Sest PHP oskab asju skripti lisada ka väljaspoolt veebikataloogi. Külastajad aga neid faile käppida ei saa..

Teine asi on see, et isegi kui kogu programm on ehk turvaline, siis üksik fail võib ikkagi haavatav olla, mistõttu tuleks neid eriti hoolsasti kaitsta.

MySQLi andmebaasiga suhtlemine

PHP pakub vahendid MySQLi andmebaasiga suhtlemiseks. Järgnevas näitame kuidas toimetada MySQLi kasutamise palas tarvitatud andmebaasiga. Andmebaasiga suhtlemiseks peab PHP skript kõigepealt näitama andmebaasiserveri nime, kasutajanime, parooli ning kasutatava andmebaasi nime. Praktiliselt tähendab see, et need väärtused tuleb sisestada PHP skripti avatekstina, mis pole aga tingimata ebaturvaline, kuna PHP skripti ennast veebikoha külataja ei näe.

23

Page 24: PHP tutvustus

Andmebaasi kirjete kuvamine

PHP + MySQL

PHP ühendamine MySQL andmebaasiga käib komplekti erikäskude abil. Kogu vastav käsustik on ära toodud PHP manuaalis.

Kõigepealt peame looma andmebaasi serveriga ühenduse ja siis valima vajaliku baasi.

1. /* loome ühenduse andmebaasiga pannes kirja serverinime, kasutajanimi ja parool */

2. $yhendus = mysql_connect("$serverinimi", "$MySQLi_kasutaja", "$parool");

3. /* valime andmebaasi - sama, mis MySQLi use-käsk */ 4. mysql_select_db("$baasi_nimi", $yhendus);

Kui ühendus on olemas ja baas valitud, võime hakata tegema päringuid.

5. $tulemus = mysql_query("SELECT * FROM kalad;");

Nüüd on meil vaja neid tulemusi kuidagi kätte saada. Selleks on vaja teada, kui palju ridu saadud päringus on.

6. $ridu = mysql_num_rows($tulemus);

Kui tulemuse ridade arv on teada, saame tulemuse väljastada veebilehele.

7. if($tulemus) { /* kontrollime, et tulemus ei oleks tühi */ 8. $reanumber = 1; 9. while( $tulemustemassiiv = mysql_fetch_array($tulemus)){

while-korduslausega väljastame tulemused rida-realt lehele. Korduse tingimuseks olev mysql_fetch_array loeb tulemuse rida-realt massiivi nimega tulemustemassiiv.

10. echo $reanumber .". - ".$read["nimi"]; /* andmebaasivälja "nimi" sisu */ 11. echo " - ".$read["telefon"]."

\n"; /* andmebaasivälja "telefon" sisu */ 12. $reanumber++; /* reanumber suureneb ühe võrra - võetakse järgmine

rida 13. } 14. }

Tulemused ilmuvad veebilehele samas järjekorras kui nad on andmebaasis.

Andmebaasi kirjete lisamine

24

Page 25: PHP tutvustus

Skript lisab andmebaasi kirje

$ab = mysql_connect("server", "kasutaja", "parool"); // valime andmetabeli mysql_select_db("db nimi",$ab); // kirjeldame päringu $sql = "INSERT INTO rahvas VALUES ('$nimi','$vanus','$elukoht')"; // teostame päringu $tulemus = mysql_query ($sql); echo "<p>Asi valmis!<p>";}?><form method="post" action="<? echo $PHP_SELF ?>">Nimi:<input type="textbox" name="nimi"><br>Vanus:<input type="textbox" name="vanus"><br>Elukoht:<input type="textbox" name="elukoht"><br><input type="submit" name="submit" value="Sisestan andmed"></form>

Näide illustreerib ka ühte PHP skriptidele iseloomulikku asjaolu - skript kutsub ennast ise taas välja. Nimelt, esmakordsel skripti brauserisse laadimisel pole ilmselt veel vajutatud submit nuppu ja seetõttu on muutuja $submit väärtustamata. Tingimuse if ($submit) plokk jäetakse täitmata ja esitatakse ainult vorm. Vormi ACTIONiks oleva muutuja $PHP_SELF väärtus on alati võrdne skripti URLiga, näiteks http://www.zoo.edu.ee/skript.php. Täiteks vormi ja valides OK kutsutakse see sama PHP skript välja, kuid muutuja $submit on nüüd väärtustatud ja seetõttu täidetakse if tingimusele järgnev plokk. See plokk suhtleb andmebaasiga.

Andmebaasi ühendus lõpetatakse automaatselt peale skripti täitmise lõppu.

25