Funktsioonid klassis Mõne või mõnekümne loodava funktsiooni puhul saab nad mugavalt paigutada abifunktsioonide faili (või ka mitmesse). Ning kui funktsioone arusaadavalt nimetada, siis nendega ei tohiks erilisi probleeme tekkida. Kui aga loodud funktsioonide arv jõuab sajani (või isegi tuhandeni), siis funktsioonide nimesid leida ja meenutada ja eristada läheb juba päris tülikaks. Samuti faili sees õige koha üles leidmine on küllalt suur katsumus. Samas - vähegi suurema ja mitmekülgsema lehestiku juures tekib tuhatkond funktsiooni üsna pea - eriti kui veel kasutatakse rakenduse juures mõnd varem valmis tehtud ning samuti hulgem funktsioone sisaldavat juppi. Kui veel eri moodulid tegelevad küllalt sarnaste teemadega (mis ikka ühte valdkonda suunatud rakenduse juures tarvilik on), siis on segadused funktsioonide nimedega kerged tulema. Programmeerimisteoreetikud on selleks puhuks juba aastakümnete tagant välja mõelnud objektorienteeritud programmeerimise, mis on tarkvaraarenduse juures suhteliselt valdavaks muutunud. Tema häid külgi saab kasutada ka PHP juures. PHP 5. versiooni mootor kirjutati suurelt jaolt just seetõttu üsna nullist uuesti, et objektimajandus ladusamalt välja tuleks. Ega esimeses lähenduses klassid ja objektid midagi väga maagilist olegi. Tegemist on ühe kapseldumiskihiga. Klassi ehk objektitüübi juures kirjeldatakse ära, millised muutujad (väljad) ja käsklused (meetodid) objekti juurde kuuluvad. Klassi põhjal luuakse üks või mitu isendit ehk objekti ehk eksemplari, kel siis vastavad käsklused sees ning mis saavad isendi piires ühiseid muutujaid kasutada. Näitena loome siin klassi Kaubad, mille ülesandeks on koondada enese sisse kaupade haldamisega seotud toimingud. Ainsaks muutujaks klassi sees jääb praegu toimingute teostamiseks vajalik andmebaasiühendus, tähistatuna praegu privaatmuutujana nimega $ab. Privaatmuutujatele pääseb ligi ainult sama klassi käskluste ehk meetodite seest. Kui eelmistes näidetes oli meil globaalmuutuja nimega $yhendus ning igas seda kasutavas funktsioonis tuli sellele ligipääs deklareerida käskluse global $yhendus kaudu, siis nüüd on muutuja $ab kogu klassi alamprogrammide sees vabalt kasutatav. Endise $yhendus->prepare asemel tuleb lihtsalt kirjutada $this->ab->prepare. Muutuja $this abil saab pöörduda konkreetse objekti muutujate külge tema enese funktsioonide seest. Klassi põhjal eksemplari loomise juures saab algväärtustamistoimingud panna konstruktorisse. PHP 5st alates on selleks funktsioon nimega __construct. Siinses näites eeldatakse, et Kaubad-klassile antakse selle eksemplaari loomisel ette avatud andmebaasiühendus sobivasse kohta. See jäetakse tema privaatmuutujasse meelde. function __construct($yhendus){ $this->ab=$yhendus; } Klassi üldiselt niisama ja otse ei kasutata. Selle asemel luuakse tema põhjal objekt ja antakse talle vajalikud algväärtused. $kaubahaldur=new Kaubad($yhendus); Hilisemad toimingud tehakse siis juba loodud kaubahalduri objekti kaudu. Kui ennist võisin otse käivitada funktsiooni kysiKaupadeAndmed, siis nüüd peab sel objekti nimi ees olema. Ehk siis käivituskujuks on $kaubahaldur->kysiKaupadeAndmed. Kirjaviis läheb küll pikemaks. Kuid selle eest pole muret, kui keegi kusagil mujal loob ka käskluse kysiKaupadeAndmed. Kumbki tuleb välja lihtsalt eraldi objekti kaudu ning käsklused üksteist ei sega. print_r($kaubahaldur->kysiKaupadeAndmed("hind")); Rippmenüüga seotud käsklused jäid kaupade klassist välja, sest neid võib vaja minna ka mujal kui kaupade juures. Sageli paigutatakse vajaminevad klassid eraldi omanimelistesse failidesse. St. et klass Kaubad võiks olla failis nimega Kaubad.class.php. Iseenesest hea tava - eriti kui klasse on rohkem ja neid vaja leida ja nende vahel orienteeruda. Siin näiteks aga jääme parem kujule, kus kõik abivahendid on failis nimega abifunktsioonid.php ab=$yhendus; } function kysiKaupadeAndmed($sorttulp="nimetus", $otsisona=""){ $lubatudtulbad=array("nimetus", "grupinimi", "hind"); if(!in_array($sorttulp, $lubatudtulbad)){ return "lubamatu tulp"; } $otsisona=addslashes(stripslashes($otsisona)); $kask=$this->ab->prepare("SELECT kaubad.id, nimetus, grupinimi, kaubagrupi_id, hind FROM kaubad, kaubagrupid WHERE kaubad.kaubagrupi_id=kaubagrupid.id AND (nimetus LIKE '%$otsisona%' OR grupinimi LIKE '%$otsisona%') ORDER BY $sorttulp"); $kask->bind_result($id, $nimetus, $grupinimi, $kaubagrupi_id, $hind); $kask->execute(); $hoidla=array(); while($kask->fetch()){ $kaup=new stdClass(); $kaup->id=$id; $kaup->nimetus=htmlspecialchars($nimetus); $kaup->grupinimi=htmlspecialchars($grupinimi); $kaup->kaubagrupi_id=$kaubagrupi_id; $kaup->hind=$hind; array_push($hoidla, $kaup); } return $hoidla; } function lisaGrupp($grupinimi){ $kask=$this->ab->prepare("INSERT INTO kaubagrupid (grupinimi) VALUES (?)"); $kask->bind_param("s", $grupinimi); $kask->execute(); } function lisaKaup($nimetus, $kaubagrupi_id, $hind){ $kask=$this->ab->prepare("INSERT INTO kaubad (nimetus, kaubagrupi_id, hind) VALUES (?, ?, ?)"); $kask->bind_param("sid", $nimetus, $kaubagrupi_id, $hind); $kask->execute(); } function kustutaKaup($kauba_id){ $kask=$this->ab->prepare("DELETE FROM kaubad WHERE id=?"); $kask->bind_param("i", $kauba_id); $kask->execute(); } function muudaKaup($kauba_id, $nimetus, $kaubagrupi_id, $hind){ $kask=$this->ab->prepare("UPDATE kaubad SET nimetus=?, kaubagrupi_id=?, hind=? WHERE id=?"); $kask->bind_param("sidi", $nimetus, $kaubagrupi_id, $hind, $kauba_id); $kask->execute(); } } /** * Luuakse HTML select-valik, kus v6etakse v22rtuseks sqllausest tulnud * esimene tulp ning n2idatakse teise tulba oma. */ function looRippMenyy($sqllause, $valikunimi, $valitudid=""){ global $yhendus; $kask=$yhendus->prepare($sqllause); $kask->bind_result($id, $sisu); $kask->execute(); $tulemus=""; return $tulemus; } function rippMenyyAndmed($sqllause){ global $yhendus; $kask=$yhendus->prepare($sqllause); $kask->bind_result($id, $sisu); $kask->execute(); $hoidla=array(); while($kask->fetch()){ $hoidla[$id]=$sisu; } return $hoidla; } $kaubahaldur=new Kaubad($yhendus); //--------------- if( array_pop(explode("/", $_SERVER["PHP_SELF"]))=="abifunktsioonid.php"): ?>
kysiKaupadeAndmed("hind"));
?>
Ülesandeid * Paiguta eelnevalt loodud inimeste andmeid haldavas rakenduses inimestega seotud funktsioonid eraldi klassi. * Muuda halduslehel funktsioonide väljakutse kuju selliselt, et haldusleht suudaks kasutada eraldi klassis leiduvad inimeste andmetega tegelevaid funktsioone ning leht töötaks. Smarty lehemallid Programmeeritavate veebilehestike juures on juba algusest peale püütud programmiosa ja kujundust võimalikult eraldada - et kujundajad saaksid rahus lehe väljanägemise kallal töötada ning et programmikood ei muutuks väljatrükitavate kujunduslõikude tõttu pikaks ja halvasti loetavaks. Samuti võimaldab selline eraldatus sama sisu ja funktsionaalsusega lehe kujundust märgatavalt muuta (näiteks ühildada veebilehestikke kahe firma ühinemisel) ilma, et peaks andmehalduse ja arvutuste poolt kuigivõrd muutma. Mõnelgi programmeerijal on tavaks küllalt palju erineva sisu ja kujundusega lehti koondada ühe faili alla. Vahel paistab terve keerukas veebilehestik vaid index.php kaudu. Ka sellisel juhul on lehemallidest märatavalt kasu - eri kujundusega lõigud saab mugavasti eraldi failidesse paigutada. Võrreldes mõne muu veebitehnoloogiaga (nt. Java Servletid, PERL) saab PHP koodi enesegagi küllalt hästi lehemalli rolli täita. Siingi materjalis tehtud näidetes on eraldi abifunktsioonid ja eraldi kujundusleht ning mõningane sisu ja vormi eraldatus on saavutatud. Seetõttu mõnigi väidab, et PHP jaoks pole eraldi mallide (template) süsteemi vaja, et PHP oma lehe loomise vahendid on selleks eraldatuseks kõige selgemad ja paremad. Ei oska talle vastu vaielda, kuid vaidlejaid siiski leidub, kes on vastava süsteemi kokku pannud. Tuntumad lehemallide süsteemid ehk Smarty, phpBB ja PatTemplate, kuid erisuguseid enese ja või oma firma jaoks aretatud PHP lehemallide süsteeme on maailma peal kindlasti tuhandeid. Siinse kirjutise autor näiteks teab Eesti pealt päris mitut inimest ja firmat, kes kõik oma lehtede mugavamaks haldamiseks on selle tarvis sarnase süsteemi kirjutanud. Siin tutvustame lehemallinduse võimalus Smarty näitel. Projekti koduleht on http://www.smarty.net/, kust saab ka abiinfot ning lähtekoodi mallsüsteemi paigaldamiseks oma serverisse. Tüüpiline Smarty abil lehe näitamise moodus koosneb vähemalt kahest lehest: tpl-laiendiga lehemall, kus HTMLi sees kirjas muutujad ja mõningad piiratud süntaksiga programmikäsud ning käivitav PHP- leht, kes annab tpl-failile kaasa vajalikud andmed ning palub siis mallilehte nende andmetega näidata. Smarty lähtekoodi lahtipakkimisel tuleb silmas pidada, kus kataloogis asub fail nimega Smarty.class.php. Siinses versioonis leiab ta asukohast Smarty-2.6.26/libs/Smarty.class.php TPL-failis tuleb näidatavate muutujate andmed kirjutada looksulgude sisse, nagu näiteks {$kaup- >id }. Samuti on looksulgude sees käsklused. Näitena kohandame kaubahalduse faili ümber lehemalli kasutama. Smarty lehemalli kasutuseks tuleb luua jooksvale kaustale alamkataloogid nimedega templates ning templates_c. Esimesse neist pannakse loodud tpl-fail, teise kompileerib Smarty käivitatava vahetulemuse. Kaustale templates_c tuleb anda kõik õigused, et Smarty pääseks sinna sisu kompileerima ja pärast käivitama. HTML-fail hakkab peale nagu tavaliselt. Mõnikord pannakse sinna kommentaar, et leht tehtud Smarty abil, aga see pole kohustuslik. Esimene tähelepanu äratav koht on kaubagruppide rippmenüü loomine. Smarty käsk html_options võimaldab teha rippmenüü. Talle antakse praegusel juhul ette massiiv nimega $gruppide_andmed, kus massiivi iga elemendi indeksiks on näidatava kaubagrupi id ning väärtuseks selle grupi nimi. Select-valiku nimi tuleb parameetrist name, ehk kaubagrupi_id samuti nagu vahal PHP-lehel tehti. {html_options name=kaubagrupi_id options=$gruppide_andmed} Järgmine suurem märkamist vajava koht on kaupade andmete läbikäimine. Tsükkel foreach käib läbi etteantud kaubaobjektide massiivi nimega $kaupade_andmed. Iga ringi peal saab konkreetse kauba andmed kätte muutujast nimega kaup - just nii nagu item-pärameetris näidatud. Valikulausega if kontrollitakse, kas tegemist muudetavate andmetega kaubaga. Kui jah, siis antakse andmerida muudetavate sisestuselementidega. Rippmenüü puhul saab ette anda ka valitud väärtuse - sarnaselt nagu me omaloodud rippemenüü loomise funktsioonid. Ning veebilehel siis ka keeratakse selle väärtusega valik ette. Andmete niisama näitamine jääb else-ossa. Kaubaobjektilt saab andmeid küsida sarnaselt nagu tavalise PHP juures. St., et hind näidatakse välja kujul {$kaup->hind } {foreach from=$kaupade_andmed item=kaup} {if $muutmisid==$kaup->id} ... {html_options name=kaubagrupi_id options=$gruppide_andmed selected=$kaup->kaubagrupi_id} ... {else} ... {$kaup->hind } {/if} {/foreach} Ning fail tervikuna. templates/kaubahaldus.tpl Kaupade leht Lahku haldamisest

Kauba lisamine

Nimetus:
Kaubagrupp:
{html_options name=kaubagrupi_id options=$gruppide_andmed}
Hind:

Grupi lisamine

Kaupade loetelu

{foreach from=$kaupade_andmed item=kaup} {if $muutmisid==$kaup->id} {else} {/if} {/foreach}
Haldus Nimetus Kaubagrupp Hind
{html_options name=kaubagrupi_id options=$gruppide_andmed selected=$kaup->kaubagrupi_id} x m {$kaup->nimetus } {$kaup->grupinimi } {$kaup->hind }
Mallifail iseseisvalt ei käivitu. Tema väljakutseks peab olema PHP-fail. Sinna sisse saab panna/jätta kõik muud koodilõigud, mis muidu kippusid lehe kujunduse kokkupanekut häirima. Samuti tuleb siin Smarty lehemallile kõik muutujatest pärinevad väärtused ette anda, et mallil neid kusagilt võtta oleks. Käsklus session_start() ning kasutajanime kontroll on tulnud juurde - et igaüks siia lehele niisama vabalt sisse ei saaks. Meldimisleht ise näha veidi tagapool. Lühiseletuseks, et kui sessioonimuutujasse pole salvestatud kasutajanime, siis sellest võib järeldada, et inimene ei ole administreerimislehele saamiseks sisse loginud ning saadetakse edasi meldimislehele. Grupi lisamine, kauba lisamine, kustutamine ja muutmine on sarnased nagu ennegi. Uus osa hakkab Smartyga seoses. Kõigepealt loetakse sisse Smarty klassi fail, mis ise sealt ülejäänud vajalikud asjad enesele külge haagib. Sealt sisseloetud klassi põhjal tehakse uus Smarty-tüüpi objekt, mille kaudu siis edasine suhtlus lehemalliga käib. Käsuga assign määratakse üksikud andmed Smarty- mallilehe muutujate külge. Lisamise rippmenüü jaoks gruppide andmed, kaupade tabeli näitamiseks kaupade andmed. Ning ühe kaubarea näitamiseks muudetaval kujul selle rea muutmisid. Kusjuures siin hoolitsetakse, et selle muutuja väärtus veateadete vältimiseks ikka olemas oleks. Kui ka tegelikult muuta ei soovita ning $_REQUEST["muutmisid"] puudub, siis pannakse selleks väärtuseks võimatu väärtus: -1. Edasi juba käsklus display soovitud malli näitamiseks ning võibki lehte imetleda. require("Smarty-2.6.26/libs/Smarty.class.php"); $smarty=new Smarty; $smarty->assign("gruppide_andmed", rippMenyyAndmed("SELECT id, grupinimi FROM kaubagrupid")); $smarty->assign("kaupade_andmed", $kaubahaldur->kysiKaupadeAndmed()); $smarty->assign("muutmisid", isSet($_REQUEST["muutmisid"])?intval($_REQUEST["muutmisid"]):-1); $smarty->display('kaubahaldus.tpl'); $yhendus->close(); Ning mallilehte käivitav PHP-leht tervikuna - saabuvate andmete püüdmine, nendele reageerimine ning lõpus mallilehe näitamiseks vajalikud toimingud. lisaGrupp($_REQUEST["uuegrupinimi"]); header("Location: kaubahaldus.php"); exit(); } if(isSet($_REQUEST["kaubalisamine"])){ $kaubahaldur->lisaKaup($_REQUEST["nimetus"], $_REQUEST["kaubagrupi_id"], $_REQUEST["hind"]); header("Location: kaubahaldus.php"); exit(); } if(isSet($_REQUEST["kustutusid"])){ $kaubahaldur->kustutaKaup($_REQUEST["kustutusid"]); } if(isSet($_REQUEST["muutmine"])){ $kaubahaldur->muudaKaup($_REQUEST["muudetudid"], $_REQUEST["nimetus"], $_REQUEST["kaubagrupi_id"], $_REQUEST["hind"]); } require("Smarty-2.6.26/libs/Smarty.class.php"); $smarty=new Smarty; $smarty->assign("gruppide_andmed", rippMenyyAndmed("SELECT id, grupinimi FROM kaubagrupid")); $smarty->assign("kaupade_andmed", $kaubahaldur->kysiKaupadeAndmed()); $smarty->assign("muutmisid", isSet($_REQUEST["muutmisid"])?intval($_REQUEST["muutmisid"]):-1); $smarty->display('kaubahaldus.tpl'); $yhendus->close(); ?> Ülesandeid * Koosta lihtne tervitav Smarty-leht, käivita PHP kaudu * Anna PHP kaudu edasi tervituslause * Smarty-lehel saab sisestada kaks arvu. Sinnasamasse väljastatakse nende korrutis. * Koosta massiiv maakondade loeteluga. Näita nad Smarty-lehel nummedamata loetleus