Professional Documents
Culture Documents
PHP Tutvustus
PHP Tutvustus
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
• 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 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.
2
Andmetüübid
PHP toetab järgmisi andmetüüpe:
Tekstiväärtused:
Nagu MySQLi puhul, kasutatakse ka PHP-s juhtsümboleid ehk eritähendusega
tekstiväärtusi. Mõned olulisemad:
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
<h1>Tere päevast!</h1>
<p>Mina olen PHP skritp.</p>
</body>
</html>
"Tere päevast!
Mina olen PHP skript."
Veebiserver asendab <? ja ?> märkide vahel asuva PHP käskude väljundiga, antud
juhul tekstiga.
kuid kui viimase käsu puhul võib semikooloni kirjutamata jätta, näiteks
PHP skripti sisse saab kirjutada kommentaare eristades nad sarnaselt C keele
traditsioonile /* ja */ märkidega muust tekstist
Include
<?
include "tere.html";
?>
<body>
<h1>Tere</h1>
</body>
4
$kordaja_1
<?
$a = -15.5; $b= 20;
$c = $a + $b;
?>
<?
echo "$a liita $b on $c";
?>
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";
?>
$a = 5;
$a = $a + 4;
$a = 5;
$a += 4;
$aeg=`date`;
5
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
<?
$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}
6
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";
}
date("H")
<?php
$lause1="Teretulemast minu kodukale, ilus päev täna!";
$lause2="Teretulemast minu kodukale, ööloom sihuke :)";
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
for ($i = 1; $i < 6; $i++)
{
echo "$i";
}
$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
} 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
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";
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.
$b = 5;
$c = -2;
$korrutis = $b * $c;
echo '$b korda $b on $korrutis';
9
Tulemus: $b korda $b on $korrutis
$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";
Tulemus: 2 * 3 on võrdne 6
10
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";
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;
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
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)
12
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")];
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
Omades sõna
13
$sone = "Priit Jaan Memm Kana Ivo";
kus " +" on regulaaravaldis. Kui tulevase massiivi elemente eraldaks üks tühiks, võiks
kasutada sarnaselt käsku explode.
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
14
$mass = array ("Priit", "Jaan", "Memm", "Kana", "Ivo");
$elementide_uus_arv = array_unshift ($mass, "Laine", "Jaa");
$elementide_uus_arv = array_push ($mass, "Leo", "Liina");
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
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
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
Lahendus:
Switchi kasutamine:
PHP kood:
switch($f)
{
case slash:
include('slash.php');
break;
case dot:
include('dot.php');
break;
default:
include('ava.php');
}
PHP kood:
<?php
include($url);
?>
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:
Sest kui nimi juhtub olema kasutaja sisestatav muutuja, siis asi see tal oma nimeks
17
kirjutada:
kala or admin=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..
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:
18
...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:
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.
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
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().
Kui muutujad on ette nähtud formist tulema, siis ära kasuta kuju:
$muutuja
vaid
$HTTP_POST_VARS['muutuja']
sessioonimuutujad:
$HTTP_SESSION_VARS['muutuja']
cookiemuutujad:
$HTTP_COOKIE_VARS['muutuja']
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:
PHP kood:
20
//defineerimine
define(KONSTANDINIMI, 'v22rtus');
//kasutamine
echo constant(KONSTANDINIMI);
//ka lihtsalt echo KONSTANDINIMI; töötab
...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';
21
Cookie kui andmete hoidja.
Miks?
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
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.
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.
23
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.
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);
24
Skript lisab andmebaasi kirje
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.
25