Teeme tutvust PHP-ga

PHP-d kasutatakse dünaamiliste veebilehtede loomiseks. PHP töötab veebiserveris ning väljastab tavalist HTML teksti. PHP-d võib näiteks kasutada selleks, et vahendada andmebaasi läbi veebi. PHP skripti kood kirjutatakse märgiste <?php ja ?> vahele. Faili laiendiks peab olema .php, vastasel juhul veebiserver PHP koodi ei töötle. Mitte .php laiendiga failidesse PHP skripti ei tohi panna sest sealt ei oska veebiserver seda kävitada. Tulemuseks näidatakse kasutaja hoopis PHP skripti lähtekoodi ennast ja nii võib lekkida sisseskirjutatud parool või lahendata jäänud turvanõrkus.

PHP eeliseks on keele lihtsus:

  • Puudub vajadus muutujate tüüpe määrata.
  • Kõik muutujate nimed algavad $ märgiga.
  • Muutujad elavad kogu .php faili piires. See tähendab, et lehe alguses ühes <?php ?> osas määratud muutuja on kasutatav hiljem korduvalt <?php ?> osas.
  • Kommentaaride read algavad //, lõigud algavad /* ja lõpevad */.
  • Funktsioonid määratakse function nimi($var1, $var2) { ... } $var1 ja $var abil saame viia muutujate väärtusi funktsiooni sisse. Funktsiooni sees saame globlaalsed muutujaid kasutada kui lisame global eesliite. Nt function nimi($var1, $var2) { global $amet; }. Nüüd on väljaspoole funktsiooni kasutusel olenud muutujat $amet kasutada ka funktsiooni nimi sees.
  • Süsteemsed muutujad on kujul $_nimi, meile olulised on $_GET ja $_POST väärtused. Nagu ka nimed ütlevad, siis muutujasse $_GET salvestatakse veebiserverile esitatud päring. Päring on nähtav veebilehitseja aadressireal Näiteks https://www.google.com/search?q=php. $_POST aga veebiserverile saadetud andmed. Saadetavad andmed ei ole nähtavad aadressireal. Näiteks vormi täitmine või faili üleslaadimine. Samas päringuga saab ka andmeid saata väikeses koguses ja lihtsustatud kujul. Nt http://192.168.4.1/andmed.php?eesnimi=kiisu&perenimi=miisu&vanus=3&varv=kollane. Kas meenutab väga muutujatele väärtuste andmist? Muutujad on & märgiga eraldatud.
  • Massiiv (Array) on ühe nimetaja alla kogutud erinevad väärtused ehk massiivi elemendid. Massivi indeksiks (elemendi järekorranumbriks) võib olla number või tekst (siis on indeksi asemel sõna võti). Kui indeksit või võtit pole määratud siis esimesel elemendil on see 0.

Vaata lisaks eesikeelseid juhendeid:

1. osa. Esimene PHP skript

/var/www/html kausta loo failid/kasutad juurkasutaja õigustes.

  • Liigu kausta /var/www/html.
  • Tee uus fail test.php kasutades käsku touch (touch test.php).
  • Kasuta Midnight Commander-it või nano (nano test.php), et muuta faili sisu.

test.php sisu kirjuta sarnane. Kohanda oma äranägemise järgi. Pöördu veebilehitsejaga http://192.168.4.1/test.php. Proovi muuta faili laiendit, php pealt html-iks. Vaata uuesti veebilehitsejaga, mis juhtus?

<?php
$eesnimi = "Mari";
$perenimi = "Maasikas";
$vanus = 18;
$aadress["linn"] = "Pärnu-Jaagupi";
$aadress["indeks"] = "87201";
$aadress["maakond"] = "Pärnumaa";
$aadress["riik"] = "Eesti";
$aadress["tanav"] = "Kooli";
$aadress["maja"] = 3;
?>
<!DOCTYPE html>
<html>
<head>
<title>PHP proov</title>
</head>
<body>

<h1>Tere maailm!</h1>
<p><?php echo "Minu nimi on: $eesnimi $perenimi"; ?></p>
<p>Minu aadress on: <?php echo "".$aadress["tanav"]." ".$aadress["maja"].", ".$aadress["linn"]." (".$aadress["indeks"]."), ".$aadress["maakond"].", ".$aadress["riik"]."."; ?></p>

</body>
</html>

Edasi lisame $_GET päringu osa. Pane tähele, et $_GET on massiiv. Päring kirjuta nii: http://192.168.4.1/test.php?nimi=mati&vanus=15&aadress=karu%20koobas.

<p><?php print_r($_GET); ?></p>

print_r() trükib massiivi sisu. %20 tähendab tühikut, mida muidu aadressis olla ei saa. $_GET võib kasutada samamoodi nagu $aadress. Proovi tekitada olukord, kus ekraanile kuvatakse päringuga saadud nimi ja elukoht.

2. osa. Päringuga saabunud andmeid tuleb kontrollida

Enne andmeid andmebaasi kirjuta hakkamist, tuleb neid kontrollida. Kas vastavad ikka mõistlikule vahemikule (temeperatuur), ega sisalda keelatud asju (teksti kujul andmed). Kui filtreerimata andmed edastada otse andmebaasi, siis on võimalik korraldada SQL injection rünnak (Vaata https://portswigger.net/web-security/sql-injection).

Enne seda tuleb aga kontrollida kas päring üldse õigesti on koostatud. Kuna mõõdame temperatuuri, õhuniiskust ja müra ning nimetame need vastavalt temp, humi, noise. Vastav päring http://192.168.4.1/test.php?temp=-5.6&humi=43.2&noise=120. Selleks kasutame programmikäske isset() ja if.

if (isset($_GET["temp"]) && isset($_GET["humi"]) && isset($_GET["noise"])) {
    echo "Andmed olemas";
} else {
    echo "Andmed puudulikud!";
}

isset() – tagastab tõene või väär, vastavalt sellele kas $_GET sisaldab elementi võtmega nimi jne.

Nagu ka Arduino C++ keeles programmeerimisel, saab siin if-i juures kasutada JA (&&) ja VÕI (||).

Kontrollime, kas andmed vastavad etteantud mustrile. Selleks kasutame programmikäsku preg_match(). See tagastab 1, kui vastab ja 0 kui ei vasta etteantud mustrile. Muster on koostatud kasutades regulaaravaldisi. preg_match() esimene argument on muster ja teine tekstiline avaldis ehk string, mille peal mustrit proovitakse.

if (preg_match("/^-?\d{1,2}\.\d{1}$/i", $_GET["temp"]) == 1 && preg_match("/^-?\d{1,2}\.\d{1}$/i", $_GET["humi"]) == 1 && preg_match("/^\d{1,3}\.\d{1}$/i", $_GET["noise"]) == 1) echo "Andmed vastavad. ";
else echo "Andmed ei vasta. ";
  • / … /i – kaldkriipsude vahel on muster, i tähendab, et suur ja väiketähe erinevust ei kontrollita.
  • ^ – alguse märk, algus peab järgnema sellele märgile. Kontrollib, oleme avaldise alguses.

Edasi on paaride kaupa:

  • -? – miinusmärk ja ? tähendab miinusmärgi esinemist ühe korra või üldse mitte. Kontrollib kas arv on negatiivne või mitte ehk kas omab miinusmärki.
  • \d{1,2} – \d tähendab numbrit ja {1,2} selle arvu esinemist 1 kuni 2 korda. Kontrollib, kas järgneb üks kuni kaks numbrit.
  • \. – punkt, peab olema nii nagu kirjutatud (üks kord). Kontrollib kas järgneb punkt.
  • \d{1} – arv peab esinema täpselt ühe korra. Kontrolib kas järgneb täpselt 1 number.
  • $ – lõpumärk, sellega avaldis lõpeb. Kontrollime, kas sellega avaldis lõpeb.

Selline muster kattub: -5.2 või 6.9 või 99.0. Ei kattu: -5 või 9 või 100.

Väga hea töövahend regulaaravaldiste õppimiseks on https://regexr.com/.

Pane tähele, siin on if tingimus kirjutatud veidi teistmoodi ja see on lubatud. Kui if (…) järgneb ainult üks programmikäsk, siis ei pea seda { ja } abil ümbritsema. Sama ka else puhul.

Tee kindlaks kolmanda ehk noise muster. Katseta erinevate (võid hulluks minna) päringutega.

3. osa. Kirjutame andmed baasi

Esmalt peab meil olema andmebaasiserverisse (SQL server) loodud vastav andmebaas ja selle sisse vastav andmetabel. Samuti peab olema loodud eraldi kasutaja selle rakenduse jaoks. Juurkasutajat ei tohi kindlasti selleks kasutada mitte mingil juhul.

a) Seejärel on vaja luua spetsiaalne SQL pide (handler) mida kasutatakse päringute tegemisel ja programmi töö lõppedes mälu puhastamiseks.

SQL pideme loomiseks on programmikäsk mysqli_connect(). Selle käsu tagastatud väärtus ongi pide. See vajab nelja argumenti. 1. Serveri aadress; 2. Kasutajatunnus. 3. Salasõna. 4. Andmebaasi nimi.

$sql_pide = mysqli_connect("serveri_aadress", "kasutajanimi", "salasona", "andmebaasi_nimi");

Vea korral tagastab väär, muidu SQL pideme. Peame kontrollima.

if (!$sql_pide) echo "Viga SQL-i ühenduse loomisel. "; 
else { ... }

Pane tähele jutumärki IF lauses väite ees! See on lihtsustatud kujul pöördvõrdelisus, mida pikemalt saaks kirjutada if ($sql_pide === false) echo … , ja siin on kolm võrdusmärki vajalik selleks, et lisaks kontrollida kas $sql_pide on boolean tüüpi.

Meie peame jätkama else osas.

b) Seame paika ühenduse parameetrid. Eriti oluline on kooditabeli määramine programmikäsuga mysqli_set_charset(). See vajab kahte argumenti: 1. SQL pide; 2. Kooditabel. Samas tuleb kontrollida kas kooditabeli määramine õnnestub.

if (!mysqli_set_charset($sql_pide, "utf8mb4_general_ci")) echo "Viga SQL-i kooditabeli määramisel. "; 
else { ... }

Meie peame jätkama mis osas?

c) Päringu tegemine programmikäsuga mysqli_query(). See vajab kahte argumenti: 1. SQL pide; 2. Pärngu tekst. Päringu teksti leiad https://roheline.pjkool.ee/2023-04/lihtsad-sql-i-paringud/ 3. osast.

$result = mysqli_query($link, "INSERT INTO `andmed` (`id`, `temp`, `humi`, `noise`, `date`, `probe`) VALUES (NULL, '1.2', '3.4', '5.6', NOW(), 'andrus1');");

Jälle tuleb kontrollida kas päringu tegemisel ilmnes vigu.

if (!$result) echo "Viga SQL päringu tegemisel. "; 
else { ... }

d) Kokku peab saama sarnase koodi:

<?php

$sql_pide = mysqli_connect("localhost", "andurid", "2YszOOVNgLGdcuk4", "andurid");

if (!$sql_pide) echo "Viga SQL-i ühenduse loomisel. ";
else {

    if (!mysqli_set_charset($sql_pide, "utf8")) echo "Viga SQL-i kooditabeli määramisel. ";
    else {

        if (isset($_GET["temp"]) && isset($_GET["humi"]) && isset($_GET["noise"]) && isset($_GET["probe"])) {

            if (preg_match("/^-?\d{1,2}\.\d{1}$/i", $_GET["temp"]) == 1 && preg_match("/^-?\d{1,2}\.\d{1}$/i", $_GET["humi"]) == 1 && preg_match("/^\d{1,3}\.\d{1}$/i", $_GET["noise"]) == 1 && preg_match("/^[0-9a-z\-]{1,10}$/i", $_GET["probe"]) == 1) {

                $result = mysqli_query($sql_pide, "INSERT INTO andmed (id, temp, humi, noise, date, probe) VALUES (NULL, '".$_GET["temp"]."', '".$_GET["humi"]."', '".$_GET["noise"]."', NOW(), '".$_GET["probe"]."');");
                if (!$result) echo "Viga SQL päringu tegemisel. ";
                else echo "OK";

            } else echo "Andmed ei vasta. ";

        } else {

            echo "Andmed puudulikud. ";

        }
    }

}

?>