OPPITUNTI 24 Esimerkki (Osa 2)

Samankaltaiset tiedostot
OSA IV Yhteenveto. Oppitunti. 23. Esimerkki (Osa 1) 24. Esimerkki (Osa 2)

OPPITUNTI 20 Tilan tallentaminen istuntofunktioilla

6. Funktiot 85. Kuinka funktioita määritellään ja kutsutaan. Kuinka funktioille viedään arvoja ja niistä palautetaan arvoja

OPPITUNTI15 Päivämäärien käsittely

OPPITUNTI 12 MySQL-tietokannan käyttö

OPPITUNTI 11 DBM-funktioiden käyttö

Harjoitustyö: virtuaalikone

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

7. Taulukot 105. Kuinka taulukoiden tietoa käsitellään ja lajitellaan

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

OPPITUNTI 19 Tilan tallentaminen evästeiden ja kyselymerkkijonojen avulla

Suvi Junes/Pauliina Munter Tietohallinto/Opetusteknologiapalvelut 2014

OPPITUNTI 5 Ohjelman kulku

OPPITUNTI 3 Ensimmäinen skripti

Tuotteiden tiedot: Lisää uuden tuotteen tiedot. Muuta tai poista tuotteen tiedot. Selaa kaikkien tuotteiden tietoja.

8. Oliot 123. Kuinka luokkia luodaan ja olioita saadaan aikaan. Kuinka luodaan ja käsitellään ominaisuuksia ja metodeja

JavaScript alkeet Esimerkkikoodeja moniste 2 ( Metropolia)

Written by Administrator Monday, 05 September :14 - Last Updated Thursday, 23 February :36

Erittäin nopea tapa saada kehitysympäristö php:lle pystyyn Voidaan asentaa muistitikulle

Makrojen mystinen maailma lyhyt oppimäärä

SQL Buddy JAMK Labranet Wiki

Järjestelmän kriittisimmille toiminnallisuuksille (listattu alla), toteutetaan 1

LIITE A Vastaukset kysymyksiin

Ohjelmoinnin perusteet Y Python

Kotisivuohjeet. Eteläpohjalaiset Kylät ry. Sivupohjien rakenne

Päivitysohje Opus Dental

Tietokannan luominen:

Pauliina Munter/Suvi Junes Tampereen yliopisto / Tietohallinto Valitse muokkaustila päälle kurssialueen etusivun oikean yläkulman painikkeesta.

OSAAMISENHALLINTA OMAT TIEDOT. Peruskäyttäjän pikaohje

Tapahtumakalenteri & Jäsentietojärjestelmä Ylläpito

Pauliina Munter / Suvi Junes Tampereen yliopisto/tietohallinto 2013

Yhdistäminen. Tietolähteen luominen. Word-taulukko. Joukkokirje, osoitetarrat Työvälineohjelmistot 1(5)

Osallistavan suunnittelun kyselytyökalu

OPPITUNTI 21 Palvelinympäristö

OSA III PHP:n käyttö. Oppitunti

Harjoituksen aiheena on tietokantapalvelimen asentaminen ja testaaminen. Asennetaan MySQL-tietokanta. Hieman linkkejä:

Proseduurit, funktiot ja herättimet - esimerkkeinä Oracle, SQL Server, MySQL ja OCELOT. Jouni Huotari S2008

AJAX-konsepti AJAX. Asynkronisuus. Nykyisten web-ohjelmien ongelmia. Asynchronous JavaScript And XML

PROSEDUURIT, FUNKTIOT JA HERÄTTIMET - ESIMERKKEINÄ ORACLE, SQL SERVER, MYSQL JA OCELOT JOUNI HUOTARI K2009

ITKP102 Ohjelmointi 1 (6 op)

INTINU13A6 Java sovellukset

Sonera Viestintäpalvelu VIP VIP Laajennettu raportointi Ohje

Tietokantasovellus (4 op) - Web-sovellukset ja niiden toteutus

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

HELIA 1 (14) Outi Virkki Tiedonhallinta

TEEMA 2 Aineistot. Kirjautuminen Moodleen. Sisältö. Kirjaudut Moodleen sivulta Voit vaihtaa kielen valikosta.

Moodle-oppimisympäristö

Zeon PDF Driver Trial

Harjoitus 3: Flash-komponenttiarkkitehtuuri ( )

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

3.1 Mitä tarkoittaan heredoc? Milloin sitä kannattaa käyttää? Kirjoita esimerkki sen käyttämisestä.

OPPITUNTI 16 Tiedon käsittely

Opetuksen suunnittelu

Google Cloud Print -opas

Sukupuu -ohjelma. Ossi Väre ( ) Joni Virtanen ( )

Maanmittauslaitoksen nimistö Spatialite-tietokantana. - kuvitettu ohje Quantum GIS ohjelmaa varten

VISUAALISEN PALVELUN TALLENNUS- JA TOISTO-OHJE

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Tutoriaaliläsnäoloista

JavaScript alkeet Esimerkkikoodeja moniste 2

Suvi Junes Tietohallinto / Opetusteknologiapalvelut 2012

KÄYTTÖOHJE / Ver 1.0 / Huhtikuu WordPress KÄYTTÖOHJE Sotkamo 2016

Tiedonhallinnan perusteet. Viikko 1 Jukka Lähetkangas

Webforum. Version 14.4 uudet ominaisuudet. Viimeisin päivitys:

Kuva: Ilpo Okkonen

Tällä viikolla. Kotitehtävien tarkistus Upotettu SQL Indeksi-harjoitus täydennetään pelifirman tietokantamallia SQL-tehtäviä

811120P Diskreetit rakenteet

Tietokannat II -kurssin harjoitustyö

Palvelinpuolen ohjelmointi

Osallistavan suunnittelun kyselytyökalu

Joomla pikaopas. Yksinkertainen opas, jossa neuvotaan esimerkkisivuston teko Joomla julkaisujärjestelmällä vaihe vaiheelta.

Toteutusdokumentti. Aija. Helsinki Ohjelmistotuotantoprojekti HELSINGIN YLIOPISTO Tietojenkäsittelytieteenlaitos

Ohjelmoinnin perusteet Y Python

Raporttiarkiston (RATKI) käyttöohjeet Ohjeet

Ohjelmoinnin perusteet Y Python

Käyttöohje. Ticket Inspector. Versio 1.0. Sportum Oy

Pikaopas. Ohjeiden etsiminen Hae ohjesisältöä napsauttamalla kysymysmerkkiä.

Entiteetit erotetaan muusta tekstistä & ja puolipiste. esim. copyright-merkki näkyy sivulla

Ohjelmoinnin perusteet Y Python

ITKP102 Ohjelmointi 1 (6 op)

Oppimateriaalin lisääminen

ICT1TN004. Lomakkeet. Heikki Hietala

DXL Library ja DXL-kielen olemus. Pekka Mäkinen SoftQA Oy http/

1 PHP-sovelluksen toiminta

FinFamily PostgreSQL installation ( ) FinFamily PostgreSQL

OSAAMISENHALLINTA HENKILÖSTÖ. Esimiehen pikaohje

Kyselyn yleisrakenne:

T Hypermediadokumentin laatiminen. Sisältö. Tavoitteet. Mitä on www-ohjelmointi? Arkkitehtuuri (yleisesti) Interaktiivisuuden keinot

Ohjelmoinnin perusteet Y Python

TimeEdit opiskelijan ohje TimeEdit-instructions for students from this link

Visma Fivaldi -käsikirja Tehtävienhallinta- ohje käyttäjälle

ITKP102 Ohjelmointi 1 (6 op), arvosteluraportti

Visma Business AddOn Factoring-laskuaineisto. Käyttäjän käsikirja

1 www-sivujen teko opetuksessa

Hyperlinkin tekeminen artikkeliin

OSA I Aloitetaan. Oppitunti. 1. PHP: Kotisivusta portaaliin 2. PHP:n asentaminen 3. Ensimmäinen skriptisi. 17 Johdanto

Ohjelmoinnin jatkokurssi, kurssikoe

Helsingin Sanomat ipad

Ennakkosuunnitelman luonti

Transkriptio:

24. Esimerkki (Osa 2) 429 OPPITUNTI 24 Esimerkki (Osa 2) Luvussa 23, "Esimerkki (Osa 1)" rakensimme ympäristön, joka sallii käyttäjien kirjoittautua palveluun ja lisätä kerho- ja tapahtumatiedot järjestelmään. Nyt voimme luoda skriptejä, jotka ovat välttämättömiä, jotta tavallinen käyttäjä voisi selata järjestelmän tietoja. Tämän tunnin aiheita ovat: Kuinka luodaan funktioita, jotka erottavat tietoa useista tauluista yhdellä kyselyllä Kuinka luodaan funktioita, jotka muuttavat SQL-kyselyn rakennetta vietyjen parametrien mukaan Kuinka tallennetaan hakuasetuksia, joita istuntofunktiot käyttävät Kuinka valmistetaan puhdas tekstitieto esitettäväksi HTML-ympäristössä

430 24. Esimerkki (Osa 2) Tapahtumapäiväkirjan julkiset näkymät Nyt kun jäsenet voivat rekisteröidä kerhonsa ja tapahtumansa tietokantaamme, voimme rakentaa näkymiä, joiden kautta tavalliset käyttäjät voivat ottaa esille tuota informaatiota. Nämä näkymät antavat käyttäjälle mahdollisuuden selata tietoja hakemisen sijaan, vaikkakin tuon lisäominaisuuden laittaminen mukaan ei olisi lainkaan vaikeaa. Tässä jaksossa rakennamme näytöt, joiden kautta käyttäjä voi nähdä listauksia, jotka vastaavat hänen aluettaan tai kiinnostuksen kohdettaan halutun kuukauden kohdalla. viewevents.php Tämä viewevents.php-näkymä antaa käyttäjälle mahdollisuuden selata annettuja tapahtumia. Se on samanlainen kuin reviewevents.php-näkymä, jota käsittelimme edellisellä tunnillamme, mutta antaa käyttäjälle kuitenkin enemmän mahdollisuuksia ja joustavuutta. Se ei kuitenkaan salli tiedon muuttamista. Tämän tiedoston koodi on listauksessa 24.1. Listaus 24.1 viewevents.php 1: <?php 2: include("dblib.inc"); 3: include("date.inc"); 4: include("clublib.inc"); 5: 6: if ( isset($actionflag) && $actionflag == "showevents" ) 7: $session[viewevents] = $form; 8: elseif ( $session[viewevents] ) 9: $form = $session[viewevents]; 10: else 11: { 12: $d_array = getdate( time() ); 13: $session[viewevents][area] = "ANY"; 14: $session[viewevents][type] = "ANY"; 15: $session[viewevents][months] = $d_array[mon]; 16: $session[viewevents][years] = $d_array[year]; 17: } 18: 19: $range = getdaterange( $session[viewevents][months], 20: $session[viewevents][years] ); 21: function displayevents( ) 22: {

24. Esimerkki (Osa 2) 431 23: global $range, $session; 24: 25: $events = getevents( 0, $range, $session[viewevents][area], 26: $session[viewevents][type] ); 27: if (! $events ) 28: 29: print "No events yet for this combination<p>"; 30: return; 31: } 32: print "<table border=1>\n"; 33: print "<td><b>date</b></td>\n"; 34: print "<td><b>event</b></td>\n"; 35: print "<td><b>club</b></td>\n"; 36: print "<td><b>area</b></td>\n"; 37: print "<td><b>type</b></td>\n"; 38: foreach ( $events as $row ) 39: { 40: print "<tr>\n"; 41: print "<td>".date("j M Y H.i", $row[edate])."</td>\n"; 42: print "<td><a href=\"viewevent.php?event_id=$row[id]&".sid."\">". 43: html($row[ename])."</a></td>\n"; 44: print "<td><a href=\"viewclub.php?club_id=$row[eclub]&".sid."\">". 45: html($row[name])."</a></td>\n"; 46: print "<td>$row[areaname]</td>\n"; 47: print "<td>$row[typename]</td>\n"; 48: print "</tr>\n"; 49: } 50: print "</table>\n"; 51: } 52:?> 53: 54: <html> 55: <head>

432 24. Esimerkki (Osa 2) 56: <title>view events</title> 57: </head> 58: <body> 59: <?php 60: include("publicnav.inc"); 61:?> 62: <h1>view Events</h1> 63: <p> 64: <form action="<?php print $PHP_SELF;?>"> 65: <input type="hidden" name="actionflag" value="showevents"> 66: <input type="hidden" name="<?php print session_name()?>" 67: value="<?php print session_id()?>"> 68: <select name=form[months]> 69: <?php writemonthoptions( $range[0] );?> 70: </select> 71: 72: <select name=form[years]> 73: <?php writeyearoptions( $range[0] );?> 74: </select> 75: 76: <select name=form[area]> 77: <option value="any">any Area 78: <?php writeoptionlist( "areas", $form[area] )?> 79: </select> 80: 81: <select name=form[type]> 82: <option value="any">any type of event 83: <?php writeoptionlist( "types", $form[type] )?> 84: </select> 85: 86: <input type = "submit" value="change"> 87: </form> 88: </p>

24. Esimerkki (Osa 2) 433 89: 90: <?php 91: displayevents( ); 92:?> 93: 94: </body> 95: </html> Aloitamme koodin sisällyttämällä kirjastotiedostot dblib.inc, date.inc ja clublib.inc. Saamme näin pääsyn tiedostojen funktioihin. Lisäksi tiedostojen dblib.inc ja clublib.inc lisääminen takaa, että avaamme tietokantayhteyden ja käynnistämme istunnon. Sen jälkeen tarkistamme, onko käyttäjä lähettänyt lomakkeen sivulle, testaamalla muuttujaa nimeltä $actionflag. Vastaava kenttä (actionflag) on upotettu piilomuuttujana sivun lomakkeelle. Jos käyttäjä on lähettänyt lomakkeen, hänen valintansa tulee ohittaa aiemmin tallennetut asetukset. Edellisellä tunnilla näit, kuinka rekisteröimme assosiatiivisen taulukkomuuttujan käyttäjän istunnon kanssa tallentaaksemme kirjautumistiedot. Tällä tunnilla lisäämme samaan taulukkoon uusia elementtejä, jotka pitävät yllä käyttäjän asetuksia. Muuttuja $session rekisteröitiin käyttäjän istunnon kanssa, kun laitoimme mukaan clublib.phptiedoston. session_start(); session_register( "session" ); Käännämme nyt $session-muuttujan moniulotteiseen taulukkoon siten, että sijoitamme assosiatiiviset taulukkoelementit elementtiin nimeltä $session[viewevents]. Näin luokittelemme asetusmuuttujat sellaisiksi, että ne kuuluvat vain tälle näytölle. Käyttäjän valitsemat vaihtoehdot ovat alue, tyyppi, kuukaudet ja vuodet. Sijoitamme lomakkeen valinnat samannimisiin $session[viewevents]-elementteihin. Jos käyttäjä ei ole lähettänyt lomaketta, hän on saattanut tehdä niin aiemmin. Siinä tapauksessa on $session[viewevents]-taulukko asetettuna, mutta $actionflag-muuttuja ei. Jos niin on, asetamme $formtaulukkoon samat arvot. Se takaa, että lomake näkyy oikein asetuksin. Jos käyttäjä ei ole lähettänyt näytön lomaketta ja $session[viewevents]-elementti on tyhjä, meidän tulee muodostaa taulukko, joka perustuu oletusarvoihin. Käytämme getdate()-funktiota päivämääräindeksitaulukon muodostamiseksi. Tuota taulukkoa käytetään asettamaan $session[viewevents][months]- elementti nykyisen kuukausi-indeksin mukaiseksi ja $session[viewevents][years]-elementti nykyisen vuoden mukaan. Nyt tiedämme, että $session[viewevents][months]- ja $session[viewevents][years]-elementti sisältää nykyisen kuukauden ja vuoden ja sen, ovatko tiedot peräisin lomakkeen lähettämisestä, käyttäjäistunnosta vai oletuksena olevasta nykyisestä päivämäärästä. Viemme nuo arvot uudelle date.inc-tiedoston funktiolle nimeltä getdaterange(). Tuo funktio ottaa vastaan kuukauden ja vuoden ja palauttaa taulukon, jossa on kaksi aikaleimaa, jotka merkitsevät kuukauden alkua ja loppua. Listaus 24.2 Ote tiedostosta date.inc 1: function getdaterange( $mon, $year )

434 24. Esimerkki (Osa 2) 2: { 3: $start = mktime( 0, 0, 0, $mon, 1, $year ); 4: $end = mktime( 0, 0, 0, $mon+1, 1, $year ); 5: $end--; 6: return array( $start, $end ); 7: } Tämän funktion palauttama taulukko tallennetaan globaaliin $range-muuttujaan. Luomme funktion nimeltä displayevents(), joka kirjoittaa valitut tapahtumatiedot selaimelle. Sitä kutsutaan HTML-asiakirjan rungosta. Saadaksemme tapahtumatietotaulukon kutsumme getevents()-funktiota, joka on tiedostossa dblib.inc, jonka laitoimme mukaan aiemmin. Kohtasimme tämän funktion jo edellisellä tunnilla, mutta käytimme vain osan sen mahdollisuuksista. Listaus 24.3 Ote tiedostosta dlib.inc 1: function getevents( $club_id=0, $range=0, $area=0, $type=0 ) 2: { 3: global $link; 4: $query = "SELECT clubs.name, events.*, areas.area as areaname, 5: types.type as typename "; 6: $query.= "FROM clubs, events, areas, types WHERE "; 7: $query.= "clubs.id=events.eclub 8: AND events.area=areas.id 9: AND events.type=types.id "; 10: if (! empty( $club_id ) && $club_id!="any" ) 11: $query.= "AND events.eclub='$club_id' "; 12: if (! empty($range) ) 13: $query.= "AND events.edate >= '$range[0]' AND 14: events.edate <='$range[1]' "; 15: if (! empty($area) && $area!= "ANY" ) 16: $query.= "AND events.area='$area' "; 17: if (! empty($type) && $type!= "ANY" ) 18: $query.= "AND events.type='$type' "; 19: $query.= "ORDER BY events.edate"; 20: $result = mysql_query( $query, $link ); 21: if (! $result )

24. Esimerkki (Osa 2) 435 22: die ( "getidevents fatal error: ".mysql_error() ); 23: $ret = array(); 24: while ( $row = mysql_fetch_array( $result ) ) 25: array_push( $ret, $row ); 26: return $ret;s 27: } Vaikka tämän funktion nimenä onkin getevents(), se sieppaa paljon enemmän tietoa. Kuten voit nähdä, se ottaa vastaan neljä argumenttia: kerhon ID:n, päivämäärärajat, jotka ovat taulukossa kahtena aikaleimana, aluekoodin ja tyyppikoodin. Kaikki nämä argumentit ovat valinnaisia ja voit korvata ne joko nollalla tai arvolla false, jos et halua niitä mukaan SQL-kyselyyn. Funktio muodostaa dynaamisesti SQL-kyselyn, joka perustuu sille vietyihin argumentteihin. Ydinkysely liittää yhteen kaikki tietokannan taulut ja takaa, että kerhon, alueen ja tyypin nimi ovat mukana tulosjoukossa. $query = "SELECT clubs.name, events.*, areas.area as areaname, types.type as typename "; $query.= "FROM clubs, events, areas, types WHERE "; $query.= "clubs.id=events.eclub AND events.area=areas.id AND events.type=types.id "; Sen jälkeen lisätään muita ehtoja kyselyyn sen mukaan, onko funktion argumentteja asetettu. Parametrit $type ja $area ohitetaan myöskin, jos ne sisältävät merkkijonon "ANY". Käytännössä tämä merkitsee sitä, että mitä enemmän argumentteja funktio saa, sitä kapeamman tulosjoukon se palauttaa. Jos mitään argumentteja ei anneta, funktio palauttaa tapahtumataulukon jokaisen tapahtuman. Jos funktiolle annetaan $club_id-argumentti, se palauttaa vain kyseisen kerhon tapahtumat. Jos argumenttina annetaan $range-taulukko, palautetaan vain tuon aikavälin tapahtumat, ja niin edelleen. Lopuksi kysely lähetetään ja tulos palautetaan moniulotteisena taulukkona. Sen jälkeen meidän on vain käytävä taulukko läpi silmukassa. Käytämme jokaista edate-kenttää päivämäärän muotoilemiseksi date()-funktion yhteydessä. Sitten muodostamme linkin tiedostoon viewevent.php, joka antaa lisätietoa tapahtumasta. Sitä varten muodostamme kyselymerkkijonon, joka sisältää tapahtuman ID:n ja SID-vakion. Tässä silmukassa muodostamme myös HTML-hyperlinkin tiedostoon viewclub.php luoden kyselymerkkijonon, joka sisältää kerhon ID:n ja SID-vakion. Lopuksi tulostamme tapahtuman tyypin ja alueen nimet. Olet saattanut huomata, että edellisellä tunnilla käytimme funktiota nimeltä html(), kun tulostimme jäsenkohtaista tapahtumatietoa yhteenvetolomakkeella. Kun käymme läpi tapahtumatietoa writeevents()- funktiossa, kutsumme html()-funktiota uudelleen. Tämä funktio on käyttäjän määrittelemä ja se elää clublib.inc-kirjastossa. Se ottaa vastaan merkkijonon ja palauttaa muunnetun version, joka sopii selaimen tulostettavaksi. Erikoismerkit muunnetaan HTML-merkeiksi ja rivinvaihdot saavat BR-elementit mukaansa.

436 24. Esimerkki (Osa 2) Listaus 24.4 Ote tiedostosta clublib.inc 1: function html( $str ) 2: { 3: if ( is_array( $str ) ) 4: { 5: foreach ( $str as $key=>$val ) 6: $str[$key] = htmlstr( $val ); 7: return $str; 8: } 9: return htmlstr( $str ); 10: } 11: function htmlstr( $str ) 12: { 13: $str = htmlspecialchars( $str ); 14: $str = nl2br( $str ); 15: return $str; 16: } Kuten voit nähdä, kyseessä on kaksi funktiota. Funktio html() ottaa argumentikseen joko merkkijonon tai taulukon. Jos parametrimuuttuja sisältää taulukon, käymme sen läpi silmukassa ja muunnamme jokaisen arvon. Muutoin muunnos toteutetaan suoraan parametrimuuttujaan. Todellinen muunnos tapahtuu funktiossa htmlstr(), joka käyttää hyväkseen kahta sisäistä funktiota: htmlspecialcharacters() muuntaa jokaisen HTML-ympäristössä esityskelpoisen merkin HTML-entiteetikseen ja nl2br() lisää BR-tagit merkkijonoon tilanteen mukaan. Kun olemme asettaneet oletustiedot ja luoneet funktion, joka tulostaa tapahtumatietoa, kaikki tuo jätetään ja aletaan muodostaa lomaketta, jonka kautta käyttäjä voi valita, kuinka hän haluaa selata tapahtumia. Käyttäjän lomake on helppo rakentaa käyttämällä edellisen tunnin funktiotia, jotka osaavat tulostaa dynaamisesti HTML-koodin mukaisia OPTION-elementtejä. Kuva 24.1 esittää näytetulostuksen tiedostosta viewevents.php.

24. Esimerkki (Osa 2) 437 KUVA 24.1 Tulostus tiedostosta viewevents.php. viewclubs.php Käyttäjä saattaa haluta esittää tietokantatietoa kerhokohtaisesti, ei välttämättä tapahtumakohtaisesti. Tällöin tulosjoukko kaventuu kerhon tyypin ja alueen mukaan. Tällainen vaihtoehto tarjotaan viewclubs.php-näytön kautta. Skripti on listauksessa 24.5. Listaus 24.5 viewclubs.php 1: <?php 2: include("dblib.inc"); 3: include("date.inc"); 4: include("clublib.inc"); 5: if ( isset($actionflag) && $actionflag == "showclubs" ) 6: $session[viewclubs] = $form; 7: elseif ( $session[viewclubs] ) 8: $form = $session[viewclubs]; 9: else 10: { 11: $session[viewclubs][area] = "ANY"; 12: $session[viewclubs][type] = "ANY"; 13: } 14: function displayclubs( ) 15: { 16: global $session; 17: $clubs = getclubs( $session[viewclubs][area],

438 24. Esimerkki (Osa 2) 18: $session[viewclubs][type] ); 19: if (! $clubs ) 20: { 21: print "No clubs yet that fit these conditions<p>\n"; 22: return; 23: } 24: print "<table border=1>\n"; 25: print "<td><b>club</b></td>\n"; 26: print "<td><b>area</b></td>\n"; 27: print "<td><b>type</b></td>\n"; 28: foreach ( $clubs as $row ) 29: { 30: print "<tr>\n"; 31: print "<td><a href=\"viewclub.php?club_id=$row[id]&".sid."\">". 32: html($row[name])."</a></td>\n"; 33: print "<td>$row[areaname]</td>\n"; 34: print "<td>$row[typename]</td>\n"; 35: print "</tr>\n"; 36: } 37: print "</table>\n"; 38: } 39:?> 40: <html> 41: <head> 42: <title>view clubs</title> 43: </head> 44: <body> 45: <?php 46: include("publicnav.inc"); 47:?> 48: <P> 49: <h1>view Clubs</h1> 50: <p>

24. Esimerkki (Osa 2) 439 51: <form action="<?php print $PHP_SELF;?>"> 52: <input type="hidden" name="actionflag" value="showclubs"> 53: <input type="hidden" name="<?php print session_name()?>" 54: value="<?php print session_id()?>"> 55: <select name=form[area]> 56: <option value="any">any Area 57: <?php writeoptionlist( "areas", $form[area] )?> 58: </select> 59: <select name=form[type]> 60: <option value="any">any type of club 61: <?php writeoptionlist( "types", $form[type] )?> 62: </select> 63: <input type = "submit" value="change"> 64: </form> 65: </p> 66: <?php 67: displayclubs( ); 68:?> 69: </body> 70: </html> Kuten voit nähdä, tämä skripti on rakenteeltaan ja logiikaltaan samanlainen kuin edellinen esimerkki. Tallennamme tämän sivun istuntomuuttujat $session[viewclubs]-elementtiin. Jos käyttäjä on lähettänyt sivun lomakkeen, päivitämme istuntomuuttujat. Jos käyttäjä ei ole lähettänyt lomaketta, mutta istuntomuuttujat ovat saatavilla, sijoitamme $session[viewclubs]-arvon $form-muuttujaan. Jos kaikki muu epäonnistuu, täytämme $session[viewclubs]-taulukon oletusarvoilla. Luomme funktion displayclubs(). Sen sisältä kutsutaan dblib-inc-tiedoston uutta funktiota, getclubs()- funktiota. Tämä funktio ottaa vastaan valinnaisesti joko kerhotaulun tyyppikentän tai aluekentän arvon: Listaus 24.6 Ote tiedostosta dlib.inc 1: function getclubs( $area="", $type="" ) 2: { 3: global $link; 4: $query = "SELECT clubs.*, areas.area as areaname, 5: types.type as typename ";

440 24. Esimerkki (Osa 2) 6: $query.= "FROM clubs, areas, types WHERE "; 7: $query.= "clubs.area=areas.id AND clubs.type=types.id "; 8: if ( $area!= "ANY" &&! empty( $area ) ) 9: $query.= "AND clubs.area='$area' "; 10: if ( $type!= "ANY" &&! empty( $type ) ) 11: $query.= "AND clubs.type='$type' "; 12: $query.= "ORDER BY clubs.area, clubs.type, clubs.name"; 13: $result = mysql_query( $query, $link ); 14: if (! $result ) 15: die ( "getidevents fatal error: ".mysql_error() ); 16: $ret = array(); 17: while ( $row = mysql_fetch_array( $result ) ) 18: array_push( $ret, $row ); 19: return $ret; 20: } 21: Funktio getclubs() rakentaa dynaamisen SQL-kyselyn, joka perustuu sille vietyihin argumentteihin. Oletuksena se yhdistää kerho-, alue- ja tyyppitaulut. Jos sille viedään $type- tai $area-argumentteina jotain muuta kuin tyhjä merkkijono tai "ANY"-merkkijono, se kaventaa edelleenkin WHERE-osaa SQL-lauseesta annettujen arvojen mukaisesti. Kuten ennenkin, se palauttaa nytkin moniulotteisen taulukon. Käymme silmukassa läpi getclubs()-funktion palauttaman taulukon ja kirjoitamme nimen, alueen nimen ja tyypin nimen selaimelle. Kuten aiemminkin, kerhon nimi muodostaa nytkin osan hyperlinkistä, joka osoittaa tiedostoon viewclub.php. viewclub.php Tämä viewclub.php-näyttö esittää kaiken kerhoon liittyvän tiedon. Se voidaan ottaa esille hyperlinkkien kautta, jotka osoittavat joko tiedostoon viewevents.php tai viewclubs.php. Koodissa on mukana aiempien esimerkkien logiikkaa ja useita funktiota. Koodi on listauksessa 24.7.

24. Esimerkki (Osa 2) 441 LISTAUS 24.7 viewclub.php 1: <?php 2: include("dblib.inc"); 3: include("clublib.inc"); 4: if (! isset($club_id) ) 5: header( "Location: viewclubs.php?".sid ); 6: $club = getclubjoined( $club_id ); 7: $club = html( $club ); 8: if ( $club[mail]!= "" ) 9: $club[mail] = "<A HREF=\"mailto:$club[mail]\">$club[mail]</A>"; 10: function displayevents() 11: { 12: global $club_id; 13: $events = getevents( $club_id ); 14: if (! $events ) 15: { 16: print "No events yet for this club<p>"; 17: return; 18: } 19: print "<table border=1>\n"; 20: print "<td><b>date</b></td>\n"; 21: print "<td><b>event</b></td>\n"; 22: print "<td><b>area</b></td>\n"; 23: print "<td><b>type</b></td>\n"; 24: foreach ( $events as $row ) 25: { 26: print "<tr>\n"; 27: print "<td>".date("j M Y H.i", $row[edate])."</td>\n"; 28: print "<td><a href=\"viewevent.php?event_id=$row[id]&".sid."\">". 29: html($row[ename])."</a></td>\n"; 30: print "<td>$row[areaname]</td>\n"; 31: print "<td>$row[typename]</td>\n"; 32: print "</tr>\n";

442 24. Esimerkki (Osa 2) 33: } 34: print "</table>\n"; 35: } 36:?> 37: <html> 38: <head> 39: <title>view clubs</title> 40: </head> 41: <body> 42: <?php 43: include("publicnav.inc"); 44:?> 45: <p> 46: <h1>view club details</h1> 47: <h4><?php print $club[name]?></h4> 48: <p> 49: Area: <b><?php print $club[areaname]?></b> 50: <br> 51: Type: <b><?php print $club[typename]?></b> 52: <BR> 53: Mail: <b><?php print $club[mail]?></b> 54: </p> 55: Description:<br> 56: <b><?php print $club[description]?></b> 57: <hr> 58: <?php 59: displayevents(); 60:?> 61: </body> 62: </html> Tämä skripti vaatii $club_id-parametrin. Testaamme sen ja palautamme käyttäjän viewclubs.php-näytölle, jos emme löydä parametria. Saadaksemme informaatiota kutsumme dblib.inc-tiedoston funktiota getclubjoined(). Se ottaa argumentikseen kerhon ID:n ja palauttaa taulukon:

24. Esimerkki (Osa 2) 443 Listaus 24.8 Ote tiedostosta dlib.inc 1: function getclubjoined( $id ) 2: { 3: global $link; 4: $query = "SELECT clubs.*, areas.area as areaname, types.type as typename A "; 5: $query.= "FROM clubs, events, areas, types WHERE "; 6: $query.= "clubs.area=areas.id 7: AND clubs.type=types.id 8: AND clubs.id='$id'"; 9: $result = mysql_query( $query, $link ); 10: if (! $result ) 11: die ( "getclubjoined fatal error: ".mysql_error() ); 12: return mysql_fetch_array( $result ); 13: } Kutsumme tätä funktiota getrow()-funktion sijaan (joka voisi myöskin palauttaa kerhotietoa), koska sen muodostama SQL-kysely sisältää alueeseen ja tyyppiin liitetyt nimet. Se tekee sen suorittamalla kerho-, alue- ja tyyppitaulukoiden välisen yhdistämisen ja tuottaa palautettavaan taulukkoon lisäelementtejä nimeltä areaname ja typename. Tallennamme getclubjoined()-funktion palauttaman taulukon muuttujaan nimeltä $club. Tämä $clubtaulukko tulostetaan selaimelle asiakirjan runkoon. Määrittelemme myös funktion nimeltä displayevents(), joka ottaa argumentikseen kerhoon liittyvän tapahtumalistaa viemällä $club_id-muuttujan getevents()- funktiolle. Kuva 24.2 esittää tiedoston viewclub.php tyypillisen tulostuksen. viewevent.php Tämä viewevent.php-tiedosto sisältää skriptimme viimeisen näytön. Se tuottaa todellisen informaation kaikista yksittäisistä tapahtumista ja siihen päästään hyperlinkkien kautta miltä tahansa julkiselta sivulta, joka listaa tapahtumien yhteenvedot. Koodi on listauksessa 24.9. Listaus 24.9 viewevent.php 1: <?php 2: include("dblib.inc"); 3: include("clublib.inc"); 4: if (! isset($event_id) )

444 24. Esimerkki (Osa 2) 5: header( "Location: viewevents.php?".sid ); 6: $event = getevent( $event_id ); 7: html( $event ); 8:?> 9: <html> 10: <head> 11: <title>view event details</title> 12: </head> 13: <body> 14: <?php 15: include("publicnav.inc"); 16:?> 17: <P> 18: <h1>view event details</h1> 19: <h4><?php print $event[ename]?></h4> 20: <p> 21: Club: 22: <b> 23: <?php print "<a href=\"viewclub.php?club_id=$event[eclub]&".sid."\"> 24: $event[clubname]</a>" 25:?> 26: </b> 27: <br> 28: Area: <b><?php print $event[areaname]?></b> 29: <br> 30: Type: <b><?php print $event[typename]?></b> 31: </p> 32: Description:<br> 33: <?php print $event[edescription]?> 34: </body> 35: </html>

24. Esimerkki (Osa 2) 445 Kuten voit nähdä, näyttö on yksinkertainen. Saamme taulukon tapahtumataulukosta käyttämällä dblib.inctiedoston getevent()-funktiota. Viemme sille $event_id-muuttujan, jonka tulisi sisältää ID-arvo, joka tuli meille kyselymerkkijonon kautta. Taulukko on sitten helppoa kirjoittaa selaimelle. Voit nähdä getevent()-funktion listauksessa 24.10. Se sisältää suhteellisen yksinkertaisen SQL-lauseen, joka yhdistää kerho- ja tapahtumataulukot. Listaus 24.10 Ote tiedostosta dlib.inc 1: function getevent( $event_id ) 2: { 3: global $link; 4: 5: $query = "SELECT clubs.name as clubname, events.*, 6: areas.area as areaname, types.type as typename "; 7: $query.= "FROM clubs, events, areas, types WHERE "; 8: $query.= "clubs.id=events.eclub 9: AND events.area=areas.id 10: AND events.type=types.id 11: AND events.id='$event_id'"; 12: $result = mysql_query( $query, $link ); 13: if (! $result ) 14: die ( "getevent fatal error: ".mysql_error() ); 15: return mysql_fetch_array( $result ); 16: } KUVA 24.2 Tulostus tiedostosta viewclub.php.

446 24. Esimerkki (Osa 2) Tulevaisuus Olemme nyt työskennelleet läpi koko tapahtumapäiväkirjaskriptin. Toivon, että se kertoo hieman siitä dynamiikasta, joka liittyy pieneenkin käytännön projektiin, ja antaa tuntuman PHP:n mahdollisuuksiin. Erityisesti sinun tulisi huomata, kuinka helppoa PHP:n istuntofunktioiden on tallentaa käyttäjän asetukset sivulta sivulle. Jos käyttäjämme palaa viewevents.php-sivulle milloin tahansa yksittäisen istunnon aikana, hän näkee samat valinnat, jotka hän on tehnyt tälle näytölle aiemmin tekemänsä vierailun aikana. Ilman istuntofunktioita meidän olisi luultavasti vietävä paljon enemmän informaatiota pyynnöltä toiselle käyttämällä URL-kyselymerkkijonoja. Vaikka tapahtumapäiväkirja ei olekaan aivan täydellinen, se kuitenkin edustaa prototyyppiä, joka kykenee näyttämään käyttäjän toiminnan. Olisi hyvä lisätä muutamia piirteitä, erityisesti hakusanalla hakeminen. Olisi myös hienoa, jos käyttäjä voisi kommentoida tapahtumia. Se lisäisi kokonaan uuden ulottuvuuden skriptiin ja tekisi siitä suositumman ja vuorovaikutteisemman. Voisimme antaa kerhon ylläpitäjille mahdollisuuden sisällyttää sivuille linkkejä kuviin, jotka liittyvät kerhon toimintaan. Voisimme myös antaa kerhon toimittajille maahdollisuuden ladata kuvia suoraan selaimelta palvelimelle. Jäsenet voisivat myös kopioida tapahtumia ja laittaa tapahtumia järjestykseen. Ennen kuin skripti voidaan jaakaa asiakkaalle, haluamme muodostaa myös hallintaympäristön, jossa on työkaluja ei-tekniseen toimintaan, jossa tilejä ja tapahtumia voidaan muokata ja poistaa sekä lisätä ja muokata alue- ja tyyppiluokkia. Olet saattanut myös huomata, että skriptin tulos on nykyään hieman aneeminen. Meidän tulisi ehkä antaa tuotos visuaaliselle suunnittelijalle ja pyytää häntä muokkaamaan ulkoasua. Onneksi suurin osa koodistamme on helposti työstettävää, vaikkakin meitä saatetaan pyytää vielä muokkaamaan silmukoita, jotka tulostavat yhteenvetoja. Yhteenveto Tällä ja edellisellä tunnilla veimme päätökseen työmme, täysin toimivan Web-sovelluksen. Käytimme tekniikoita, joiden avulla tallensimme tilan, todensimme käyttäjiä, muokkasimme ja esitimme tietokantojen tietoa ja paljon muutakin. Moninäyttöistä koodiesimerkkia ei ole helppo esittää kirjassa, mutta yrittäminenkin on hyödyllistä. Olemme ottaneet esille aiheita, joihin törmäät uudelleen ja uudelleen, joten sinun tulee rakentaa strategioita tilainformaation ylläpitämiseen. K&V K No siinä se oli; mitäs seuraavaksi? V Nyt kaikki riippuu sinusta. Tämä kirja sisältää tarpeeksi informaatiota, jotta voit luoda omia kehittyneitä sovelluksiasi ja ympäristöjäsi. Kun käytät antamiamme taitoja ja hakemalla lisätietoa, mikään ei voi estää sinua!

24. Esimerkki (Osa 2) 447 Työpaja Työpaja tarjoaa joukon kertauskysymyksiä, joiden avulla voit tarkistaa, oletko ymmärtänyt materiaalin sisältöä. Yritä ymmärtää vastaukset ennen kuin jatkat seuraaviin lukuihin. Vastaukset ovat liitteessä A. Kysymyksiä 1. Millä funktiolla lisäät elementin taulukon loppuun? 2. Onko mahdollista lisätä elementti taulukkoon käyttämättä funktiota? 3. Millä funktiolla käännät erikoismerkit HTML-muotoon? 4. Millä funktiolla käännät rivinvaihtomerkit BR-tageiksi? 5. SID-vakiolla voit viedä istunnon ID:n toiselle sivulle HTML-linkin kautta. Kuinka voisit saada aikaan saman lomakkeen kautta? Toiminta 1. Tutki tämän tunnin koodia. Onko jokin tekniikoista tai aiheista sopiva omiin projekteihisi? 2. Selaile kirjaa taaksepäin ja tutki muistiinpanojasi. Jos olet seurannut kirjaa ikään kuin kurssin muodossa, muista, että omien muistiinpanojen kertaaminen täydentää suorittamasi kurssin.

448 24. Esimerkki (Osa 2)