Kirjoittaja: Antti Laaksonen (2003).
⚠ Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi. ⚠
Paitsi että funktioita käyttämällä koodin pituus pienenee, ne myös tekevät siitä selkeämmän ja helpottavat virheenkorjausta. Tämä opas sisältää perusasiat funktioiden luomisesta PHP-kielessä. Oppaan lopussa on esimerkkiprojekti, vieraskirja, jossa yhdistyvät opassarjan edellisten osien opetukset.
Funktion määrittely aloitetaan avainsanalla function
. Tämän jälkeen kirjoitetaan funktion nimi ja sulkumerkit. Funktion lausekkeet laitetaan aaltosulkujen sisään. Seuraavassa esimerkissä funktio rivi tulostaa rivin tekstiä. Funktiota kutsutaan kolmesti.
<?php function rivi() { echo "Tämä tuli funktiosta!\n"; } echo "Ensimmäinen rivi.\n"; rivi(); rivi(); rivi(); echo "Viimeinen rivi."; //Ensimmäinen rivi. //Tämä tuli funktiosta! //Tämä tuli funktiosta! //Tämä tuli funktiosta! //Viimeinen rivi. ?>
Hyvin usein funktiolle annetaan myös parametreja. Parametrit ovat muuttujia, jotka vaikuttavat funktion toimintaan. Parametrit kirjoitetaan funktion nimen perässä olevien sulkumerkkien sisään pilkuilla erotettuina. Ne ovat käytössä funktion sisällä samannimisinä muuttujina.
<?php function tiedot($nimi, $kaupunki) { echo "$nimi asuu {$kaupunki}ssa.\n"; } tiedot("Pentti", "Kuopio"); tiedot("Seppo", "Espoo"); //Pentti asuu Kuopiossa. //Seppo asuu Espoossa. ?>
Funktion parametreilla voi olla oletusarvoja, joita käytetään silloin, jos parametria ei ole annettu. Oletusarvot määritellään yhtäsuuruusmerkin avulla. Kuitenkin vain viimeiset parametrit voivat olla valinnaisia (muuten parametrit voisivat mennä sekaisin). Seuraavassa esimerkissä nimi on oletuksena "Nimetön".
<?php function tervehdys($nimi = "Nimetön") { echo "Moi, $nimi!\n"; } tervehdys(); tervehdys("Pentti"); tervehdys("Seppo"); //Moi, Nimetön! //Moi, Pentti! //Moi, Seppo! ?>
Monesti funktio palauttaa arvon, jota voidaan käyttää hyväksi funktiota kutsuneessa koodissa. Tämä tapahtuu return
-avainsanan avulla. Tämän jälkeen funktiosta poistutaan välittömästi. Seuraavassa esimerkissä euroiksi-funktio jakaa markkamäärän euron kurssilla ja pyöristää tuloksen kahden desimaalin tarkkuudelle round
-funktiolla.
<?php function euroiksi($markat) { return round($markat / 5.94573, 2); } echo "100 markkaa on " . euroiksi(100) . " euroa."; //100 markkaa on 16.82 euroa. ?>
Jos funktiossa halutaan käyttää funktion ulkopuolella olevia muuttujia, ne on määriteltävä global
-avainsanan avulla. Avainsanan perään kirjoitetaan yhden tai useamman muuttujan nimi pilkuilla erotettuina. Seuraavassa esimerkissä markan ja euron suhde haetaan funktion ulkopuolisesta muuttujasta.
<?php $suhde = 5.94573; function euroiksi($markat) { global $suhde; return round($markat / $suhde, 2); } echo "100 markkaa on " . euroiksi(100) . " euroa."; ?>
Tavallisesti funktiossa tapahtuvat virhetilanteet tuottavat virheilmoituksen aivan samoin kuin muuallakin koodissa. Oudot virheilmoitukset voivat kuitenkin aiheuttaa päänvaivaa skriptin käyttäjälle, minkä vuoksi ilmoitusten tulostuminen halutaan välillä estää. Tämä on mahdollista kirjoittamalla merkki @
funktion nimen eteen.
<?php function jako() { //jako nollalla aiheuttaisi tavallisesti ilmoituksen "Division by zero"... $osamaara = 10 / 0; } //...mutta koska funktion nimen edessä on @, virheilmoitus ei tule näkyviin @jako() ?>
On kuitenkin syytä muistaa, että tärkeät, korjausta vaativat virheet voivat samalla jäädä näkemättä. Eräs hyvä keino virheenkäsittelyyn on hyödyntää funktioiden palautusarvoja. Seuraavassa esimerkissä tiedoston rivit luetaan taulukkoon. Jos lukeminen ei onnistunut, muuttujan arvo on false, jolloin näytetään suomenkielinen virheilmoitus.
<?php $tiedosto = @file("olematon.xyz"); if ($tiedosto) { //tähän tulee tiedoston rivien käsittely } else { echo "Tiedoston lukeminen epäonnistui!"; } ?>
Opassarjan neljännessä esiintyi kuvitteellinen Villen korttipelisivu, jossa PHP:ta käytettiin sivupohjissa ja palautteen lähettämisessä. Villen PHP-taidot ovat karttuneet, ja hän päätti tehdä itse sivuilleen vieraskirjan, johon kävijät voivat lähettää palautetta ja terveisiä. Nyt tutkimme askel askeleelta, kuinka Ville rakensi vieraskirjansa.
Viestit on tallennettu tiedostoon viestit.txt, joka on tavallinen tekstitiedosto. Jokainen viesti on omalla rivillään ja viestiä kohden on seuraavat tiedot: lähettäjän nimi, lähettäjän sähköpostiosoite, lähetysaika ja viesti. Nämä tiedot on erotettu pystyviivoilla (|), joten tiedoston rakenne näyttää seuraavalta:
nimi1|email1|aika1|viesti1 nimi2|email2|aika2|viesti2 nimi3|email3|aika3|viesti3
Vieraskirja on melko yksinkertainen, joten sen käsittelyyn riittää kaksi skriptiä:
Tiedosto nayta.php alkaa tavallisella HTML-koodilla, joka sisältää otsikon ja linkin viestin lähetyssivulle.
<html> <head> <title>Vieraskirja</title> </head> <body> <h1>Vieraskirja</h1> <p><a href="laheta.php">Lähetä viesti</a></p>
Tämän jälkeen tulee PHP-osuus. Aluksi viestit luetaan taulukkoon file
-funktiolla ja taulukko käännetään ympäri array_reverse
-funktiolla. Koska viestit tallennetaan tiedoston loppuun, uusimmat viestit ovat nyt taulukon alussa. Viestien määrä on sama kuin tiedoston rivien määrä, joten se selviää count
-funktiolla.
Kun viestien määrä tiedetään, niiden läpikäyminen on helppoa for-silmukalla. Jokaisessa taulukon alkiossa on tiedostosta luettu rivi, joka sisältää viestin tiedot pystyviivoilla erotettuna. Tämä merkkijono muutetaan nelialkioiseksi taulukoksi explode
-funktion avulla. Funktio saa parametreikseen erotinmerkin, merkkijonon ja alkioiden määrän.
Taulukosta tiedot siirretään muuttujiin. Tämän jälkeen viesti on valmis tulostettavaksi sopivasti muotoiltuna. Viestin lähetysaika on tallennettu aikaleimana (numerosarja, joka kuvaa kuluneiden sekuntien määrää tammikuun 1. päivästä 1970), ja se muunnetaan ymmärrettävämpään muotoon date-funktion avulla. Muotoilumerkkijono "d.m.Y H:i" saa aikaan suomalaisen päivämäärän.
<?php //luetaan viestit taulukkoon $viestit = file("viestit.txt"); //käännetään taulukko, jolloin uusimmat viestit tulevat ylimmiksi $viestit = array_reverse($viestit); //viestien määrä on suoraan taulukon rivien määrä $viestimaara = count($viestit); //tulostetaan viestimäärä echo "<p>Yhteensä <b>$viestimaara</b> viestiä.</p><hr>"; //käydään jokainen viesti läpi for ($i = 0; $i < $viestimaara; $i++) { //$viestit[$i] on merkkijono, joka sisältää viestin $i tiedot //pystyviivoilla erotettuna; jaetaan viestit $tiedot-taulukkoon $tiedot = explode("|", $viestit[$i], 4); //erotellaan tiedot omiin muuttujiinsa $nimi = $tiedot[0]; $email = $tiedot[1]; $aika = $tiedot[2]; $viesti = $tiedot[3]; //tulostetaan viesti echo "<p><b>Lähettäjä</b>: <a href=\"mailto:$email\">$nimi</a><br>"; echo "<b>Aika</b>: " . date("d.m.Y H:i", $aika) . "<br>"; echo "<br>$viesti<hr>"; } ?>
Loppuun tulee vielä pari riviä HTML-koodia, jotka päättävät sivun.
</body> </html>
Viestin lähettämisessä on kaksi vaihetta: käyttäjä kirjoittaa viestin ja skripti tallentaa sen tiedostoon. Tässä vieraskirjassa kumpikin vaihe on jaettu samaan tiedostoon, laheta.php. Koko skriptin pohjana on itse asiassa suuri if-ehtolause
, joka määrittää, näytetäänkö viestin kirjoittamiseen tarkoitettu lomake, vai onko jo aika tallentaa viesti tiedostoon.
Jos lomakkeen kautta ei tullut muuttujaa nimeä, lomaketta ei vielä oltu lähetetty (tai käyttäjä ei ollut laittanut nimeään, jolloin viestin tallentaminen ei myöskään käy). Tällöin näytetään lomake, joka sisältää tekstikentät nimelle, sähköpostille ja viestille sekä lähetysnapin.
<html> <head> <title>Viestin lähetys</title> </head> <body> <h1>Viestin lähetys</h1> <form action="laheta.php" method="post"> Nimi: <br> <input type="text" name="nimi"> <br> Sähköposti: <br> <input type="text" name="email"> <br> Viesti: <br> <textarea name="viesti"></textarea> <br> <br> <input type="submit" value="Lähetä"> </form> </body> </html>
Jos lomake olikin jo lähetetty, on aika tallentaa uusi viesti tiedostoon. Tiedosto avataan append-tilassa, jolloin uusi viesti kirjoitetaan vanhojen viestien perään. Tämän jälkeen lomakkeen kautta tulleet tiedot haetaan muuttujiin.
Ennen kuin viestin voi tallentaa tiedostoon, siihen on tehtävä muutamia muutoksia:
stripslashes
-funktiolla.htmlspecialchars
-funktiolla.str_replace
-funktion avulla. Samalla viesti mahtuu yhdelle riville tiedostossa.Viestin lähetysaika selviää time
-funktiolla, joka palauttaa palvelimen ajan aikaleimana. Näin tallennettuna ajan muotoilua on helppo vaihtaa myöhemmin. Tämän jälkeen tiedoista muodostetaan pystyviivoilla erotettu rivi, joka tallennetaan tiedostoon. Lopuksi käyttäjä ohjataan takaisin vieraskirjasivulle header
-funktion avulla.
<?php //...muussa tapauksessa kirjoitetaan viesti tiedostoon } else { //avataan tiedosto append-tilassa: kirjoitetaan tiedoston loppuun $tiedosto = fopen("viestit.txt", "a"); //haetaan lomakkeen kautta tulleet muuttujat $nimi = $_POST['nimi']; $email = $_POST['email']; $viesti = $_POST['viesti']; //poistetaan ylimääräiset kenoviivat (\) $viesti = stripslashes($viesti); //estetään HTML-tagien käyttäminen $viesti = htmlspecialchars($viesti); //muutetaan rivinvaihdot HTML-muotoon $viesti = str_replace("\n", "<br>", $viesti); //otetaan talteen aika, jolloin viesti lähetettiin $aika = time(); //muodostetaan tiedostoon tallennettava rivi $rivi = "$nimi|$email|$aika|$viesti\n"; //kirjoitetaan rivi tiedostoon fwrite($tiedosto, $rivi); //suljetaan tiedosto fclose($tiedosto); //ohjataan käyttäjä vieraskirjasivulle header("Location: nayta.php"); } ?>
Ville kopioi palvelimelle PHP-tiedostot sekä tyhjän viestitiedoston. Viestitiedon chmod-arvoksi hän asetti 664, jotta sen muokkaaminen PHP:n kautta onnistuu. Myöhemmin Ville lisäsi vieraskirjaansa vielä viestien sivutuksen ja itselleen mahdollisuuden vastata viesteihin. Omien skriptien tekeminen onkin paras tapa oppia PHP.
Opassarjan seuraavaan osa ilmestyy joidenkin viikkojen kuluttua. Aiheita ovat ainakin evästeiden käyttö, sivujen salasanasuojaus ja tiedostojen kopiointi selaimen kautta. Kenties jokin vähän suurempi esimerkkiskriptikin mahtuu mukaan.
Antti Laaksonen, 21.5.2003
Jes, mä oon aina halunnu oppia käyttämään evästeitä. :)
Ton esimerkissä olevan kirjan voi sotkea helposti, laittaa vaan viestiin, nimeen tms. merkin "|".
Tai sitten tekee oman html-sivun ja pistää siihen textarean, jolloin voi lähettää monirivisiä viestejä kunhan pistää textarean nimeksi "nimi" ja lyö siihen vähän rivinvaihtoa..
lainaus:
Ton esimerkissä olevan kirjan voi sotkea helposti, laittaa vaan viestiin, nimeen tms. merkin "|".
Viestissä tämä ei toimi, koska taulukkoon tulee tasan neljä alkiota ja viesti on niistä viimeinen. Muissa kentissä toimii, mutta silloin häirikön oma viesti vain menee sekaisin (harvemmin oikeaan nimeen tai sähköpostiosoitteeseen sisältyy pystyviivaa).
lainaus:
Tai sitten tekee oman html-sivun ja pistää siihen textarean, jolloin voi lähettää monirivisiä viestejä kunhan pistää textarean nimeksi "nimi" ja lyö siihen vähän rivinvaihtoa..
Tämä saattaa toimia. Mutta harvapa perushäirikkö tuollaisia konsteja tuntee. Skriptiin voisi lisätä tarkistuksen, että lomake on lähetetty oikeasta osoitteesta.
Laittaisit tohon vaikka |*| niin ei menis sekasin niin helposti.
jagga
lainaus:
(harvemmin oikeaan nimeen tai sähköpostiosoitteeseen sisältyy pystyviivaa).
Ongelmana on ns. 'eliitti nimet' joissa ei voida missään tapauksessa käyttää tavallisia kirjaimia. (esim. /\/ | /\/\ | )
Mutta | merkinhän voi helposti muuttaa vaikka pieneksi älläksi tai isoksi iiksi.
miten saisi niin että kun textareasse rivi vaihtuu automaattisesti niin viestissäkin tulisi rivinvaihto
tuossa ainakin rivinvaihto tulee vain kun painetaa enteriä ei silloin kun textarea vaihtaa sitä itse automaattisesti
eiks sen saa vaihtamaan rivia kun teksti lähestyy tekstilaatikon reunaa tai kun painaa entterii: wrap=physical tai vain kun teksti lähestyy reunaa: weap=virtual
(en tiiä sitte)
Jos vieraskirjatiedostoon halutaan viestit omille riville, niin kannattaa karsia sieltä \r rivinvaihdot (telanpalautin?) pois:
$viesti = str_replace("\r", "", $viesti);
Miksi minulla tulee tulostuksessa vain:
$nimi
"; echo "Aika: " . date("d.m.Y H:i", $aika) . "
"; echo "
$viesti
"; } ?>
onhan sun palvelimella php tuki? Ja tosta puuttuu alust <?php
Tahtoisko joku selittää, miks täs on tällee:
<?php //...muussa tapauksessa kirjoitetaan viesti tiedostoon } else {
Ku miten toi eka aaltosulje. Ku sillä ei niiku oo alottavaa suljetta. Ku yksinkertastenutta aaltosulut menee tossa koodissa näin: }{}
Eli toi eka mua mietityttää.
Onpahan tossa alottajakin
periaattessa kun tuossa on htmlspecialchars viesti vain, niin emailissa ja nimessä vois käyttää html koodeja?
Siihen voi tunkea HTML-koodeja, mutta ne näkyvät niinkuin ohjelmointiputkan keskustelussa:
<b>Tämä ei ole lihavoitu</b>
Kirjoittelimpahan tähän nyt suodattimen tuolle || häiriköinnille, eli...
$nimi = str_replace("|", "I", $nimi); $email = str_replace("|", "I", $email);
Tämä | erotinhan on järkevä vain, jos ei oleta eliteporukkaa vierasille =)
voiks joku lähettää mulle zippinä noi, kaikki tiedostot mitä tosta tulee osoitteesee: aappo825@gmail.com
MAHDOLLISIMMAN PIAN
Mitähän varten vieraskirja ei toimi. tein kaikki samoin kun tos neuvotaan mut kun sinne yrittää lähettää viestin niin se ei näy sillä nayta.php sivulla. Jos avaa tiedoston viestit.txt ja kirjoittaa sinne niin se kyllä näkyy nayta.php sivulla. Eli vika on käsittääkseni laheta.php sivulla. EI YMMÄLLÄ!!!!
Joo nyt mä sain sen toimimaan. En ollu muistanu asettaa tota CHMOD arvoo oikeeks...
Väpä kirjoitti:
Mitähän varten vieraskirja ei toimi. tein kaikki samoin kun tos neuvotaan mut kun sinne yrittää lähettää viestin niin se ei näy sillä nayta.php sivulla. Jos avaa tiedoston viestit.txt ja kirjoittaa sinne niin se kyllä näkyy nayta.php sivulla. Eli vika on käsittääkseni laheta.php sivulla. EI YMMÄLLÄ!!!!
Oothan varmasti asettanu ton viestit.txt-tiedoston käyttäjäoikeudet niin, että PHP saa kirjottaa sinne? (tuo mainittu 664 on riittävä)
Tulostaako skripti jotain virheilmotusta? Mikäli tiedoston oikeudet ei oo kunnossa, ilmotus on jotain tyyliin: "Could not open file..."
Kiitoksia vieraskirjasta, Antti
Tein siitä sovelluksen ja koplasin laheta.php ja nayta.php tiedostot yhteen includen avulla. Ja ruokahalu alkoi kasvaa syödessä.
Osaako kukaan kertoa, missä olisi koodivinkki, joka mahdollistaisi vieraskirjan viestien kätevän muokkaamisen tai poistamisen?
Nyt muokkaan tekstitiedostoa Bluefishin avulla.
--
Tekstitiedostossa on yksityiskohta, joka tulee esiin, kun siivoaa tiedostoa editorilla. Viimeisen viestin jälkeen pitää olla yksi "enter" eli tulee avata tyhjä rivi. Jos turhaa enteriä ei ole, seuraava viesti menee edellisen niskaan. - Sinällään ongelmaton asia, kun sen vain tietää.
"Myöhemmin Ville lisäsi vieraskirjaansa vielä viestien sivutuksen ja itselleen mahdollisuuden vastata viesteihin". Kuinka tuo tehdään?
Nessu Maakonni kirjoitti:
"Myöhemmin Ville lisäsi vieraskirjaansa vielä viestien sivutuksen ja itselleen mahdollisuuden vastata viesteihin". Kuinka tuo tehdään?
https://www.ohjelmointiputka.net/koodivinkit/
Viestien vastaus on sitten vähän monimutkaisempi. Lueppas tämä php- opas loppuun ja yritä muutenkin oppia php:tä. Kyllä se siitä lähtee ; )
Miksiköhän minulla on tuossa vieraskirjassa viestin lähetys aika ihan väärä. Mistäköhän johtuisi?
Jostain syystä minulla ei tuo fopen funktio toimi linuxsissa. Titäisikö joku onko siihen linuxissa joku vastaava mutta erilainen funktio?
Minä kopioin vieraskirjan 1:1 ilman ongelmia fopen kanssa. Käyttiksenä Linux Fedora. Olisiko ongelma serverin päässä?
lainaus:
$viesti = str_replace("\n","<rivinvaihtotagi>",$viesti);
Tuon voi hoitaa myös funktiolla nl2br().
mull ois semmone juttu tähän, et ku teen tuol tekstikentäs rivinvaihdon, ja kun haluun sen tulostuvan niin et ain uusin viesti tulee ylimmäs, niin se nakkaa rivinvaihdon jälkeisen tekstin ylimmäs, eli otsikon ja kaikkien yläpuolelle, mistäköhän mahtaisi kiikastaa.
Aika: 11, 7, 2010:Valitse valikosta:tyuty
Aika: 11, 7, 2010:Valitse valikosta:utyuyt
tyutyu
tos on toi tekstitiedosto minne kaikki tallentuu josta otan noi. Ylin on et textareas ei oo käytetty entterii ja alemmas on käytetty entterii
Kiitos hyvästä oppasta!
//tämä estää lähettämästä html -ja php-koodia tekstiin
$viesti = str_replace("<", "& lt", $viesti);
$viesti = str_replace(">", "& gt", $viesti);
Siis noi keskellä olevat ovat ylhäällä: & lt ja alhaalla & gt, mutta välit pois.
Edit. Yksi, mikä saattaa myös aiheuttaa toimimattomuutta, on toi viestit.txt filun oikeudet. Oikeuksien täytyy olla 777, jotta php voi kirjoittaa tiedostoon! Jos oikeudet eivät ole kohillaan, virhe ilmenee siinä, että viesti ei tallennu.
Jeps muokkailen tästä projektinlisäyssysteemin omille sivuilleni, antille kiitokset :)
Joo, sekotan HTML:llää ja php:tä väärässä tapauksessa. Siis kyllä nettisivussa ne oikein kirjoitan,
mutta täällä kooditagien sisään ei onnistu.
Kuinkas tohon sais spämmisuojauksen?
Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.