Kirjautuminen

Haku

Tehtävät

Oppaat: PHP-ohjelmointi: Osa 10 - Omat funktiot

  1. Osa 1 - Johdanto
  2. Osa 2 - Muuttujat
  3. Osa 3 - if-rakenne
  4. Osa 4 - for-silmukka
  5. Osa 5 - Taulukot
  6. Osa 6 - Lomakkeet
  7. Osa 7 - Nettisivusto
  8. Osa 8 - Lisää silmukoista
  9. Osa 9 - Tiedostot
  10. Osa 10 - Omat funktiot
  11. Osa 11 - Istunnot
  12. Osa 12 - Tietokannat
  13. Osa 13 - Tietoturva
  14. Osa 14 - Olio-ohjelmointi
  15. Osa 15 - Kuvien luonti
  16. Osa 16 - Säännölliset lausekkeet
  17. Osa 17 - Merkistöt
  18. Osa 18 - PHP:n ongelmat

Kirjoittaja: Antti Laaksonen. Vuosi: 2011.

Olemme käyttäneet opassarjan kuluessa monia PHP:n valmiita funktioita. Esimerkiksi funktio strlen kertoo merkkijonon pituuden ja funktio round pyöristää luvun kokonaisluvuksi. Tässä oppaassa opimme tekemään vastaavia funktioita itse.

Funktioiden tarkoituksena on helpottaa koodin kirjoittamista ja selkeyttää sen rakennetta. Esimerkiksi jos koodissa toistuu monta kertaa lähes samanlainen osuus, tekemällä funktion samaa koodia ei joudu monistamaan.

Funktio

Seuraavassa koodissa on itse tehty funktio tervehdi:

<?php
function tervehdi() {
    echo "<i>Heippa!</i> <br>";
}

tervehdi();
tervehdi();
tervehdi();
?>

Funktio tervehdi tulostaa viestin "Heippa!" ja rivinvaihdon. Funktiota kutsutaan koodissa kolmesti, joten koodi tuottaa seuraavan sivun:

Heippa!
Heippa!
Heippa!

Parametri

Funktioon liittyy yleensä parametreja, jotka tarkentavat, mitä funktion on tarkoitus tehdä. Esimerkiksi voimme lisätä funktioon tervehdi parametrin $viesti:

<?php
function tervehdi($viesti) {
    echo "<i>{$viesti}</i> <br>";
}

tervehdi("Heippa!");
tervehdi("Moikka!");
tervehdi("Tsaukki!");
?>

Nyt funktiota kutsuessa parametri $viesti ilmoittaa, millä tavoin funktio tervehtii. Tässä tapauksessa koodi tuottaa seuraavan sivun:

Heippa!
Moikka!
Tsaukki!

Laajennetaan vielä funktiota niin, että sille voi antaa parametrina myös viestin toistokertojen määrän:

<?php
function tervehdi($viesti, $kerrat) {
    for ($i = 0; $i < $kerrat; $i++) {
        echo "<i>{$viesti}</i> <br>";
    }
}

tervehdi("Heippa!", 5);
?>

Tämän muutoksen jälkeen koodi tuottaa seuraavan sivun:

Heippa!
Heippa!
Heippa!
Heippa!
Heippa!

Esimerkki: Valintalistan luonti

Seuraavassa esimerkissä funktio valintalista helpottaa valintalistojen luontia:

<?php
function valintalista($nimi, $sisalto) {
    echo "<select name=\"{$nimi}\">";
    foreach ($sisalto as $kohta) {
        echo "<option value=\"{$kohta}\">{$kohta}";
    }
    echo "</select>";
}

echo "<p>Valitse syntymäpäiväsi:</p>";
valintalista("paiva", range(1, 31));
valintalista("kuukausi", range(1, 12));
valintalista("vuosi", range(1900, 2010));
?>

Koodi tuottaa seuraavan syntymäpäivän valinnan:

Valitse syntymäpäiväsi:

Tässä funktio range muodostaa taulukon, joka sisältää luvut annetulta väliltä. Esimerkiksi range(1, 5) tarkoittaa taulukkoa array(1, 2, 3, 4, 5).

Palautusarvo

Seuraavassa koodissa funktiolla keskiarvo on palautusarvo:

<?php
function keskiarvo($a, $b) {
    return ($a + $b) / 2;
}

echo "Keskiarvo: " . keskiarvo(3, 7);
?>

Funktiolle annetaan parametrina kaksi lukua, ja funktio palauttaa niiden keskiarvon komennolla return. Palautusarvo välittyy kohtaan, jossa funktiota kutsutaan muualla koodissa. Tässä tapauksessa koodi tulostaa "Keskiarvo: 5".

Komento return poistuu heti funktiosta, vaikka komento olisi keskellä funktiota. Komentoa voi käyttää myös ilman palautusarvoa, jolloin komennon ainoa tarkoitus on poistua funktiosta.

Esimerkki: Sähköpostiosoitteen tarkistus

Seuraava funktio tarkistaa sähköpostiosoitteen muodon:

<?php
function tarkista($osoite) {
    $pituus = strlen($osoite);
    if ($pituus < 5 || $pituus > 256) {
        return false;
    }
    if (substr_count($osoite, "@") == 1) {
        return true;
    } else {
        return false;
    }
}

if (tarkista("aapeli@ohjelmointiputka.net")) {
    echo "Osoite kelpaa!";
} else {
    echo "Osoite ei kelpaa!";
}
?>

Funktio palauttaa arvon true, jos osoite näyttää kelvolliselta, ja muuten arvon false. Funktio vaatii, että osoitteen pituus on 5–256 merkkiä ja siinä on tasan yksi @-merkki. Tässä funktio substr_count kertoo, kuinka monta kertaa merkkijono esiintyy toisen merkkijonon osana.

Tässä on sama funktio hieman lyhyemmin:

function tarkista($osoite) {
    $pituus = strlen($osoite);
    return $pituus >= 5 && $pituus <= 256 &&
           substr_count($osoite, "@") == 1;
}

Oletusarvo

Seuraavassa koodissa funktion parametreilla on oletusarvot:

<?php
function tervehdi($viesti = "Heippa!", $kerrat = 1) {
    for ($i = 0; $i < $kerrat; $i++) {
        echo "<i>{$viesti}</i> <br>";
    }
}

tervehdi();
tervehdi("Moikka!");
tervehdi("Tsaukki!", 3);
?>

Nyt funktiolle voi antaa kutsussa 0–2 parametria. Jos parametri $viesti puuttuu, oletusarvo on "Heippa!", ja jos parametri $kerrat puuttuu, oletusarvo on 1. Koodi tuottaa seuraavan sivun:

Heippa!
Moikka!
Tsaukki!
Tsaukki!
Tsaukki!

Kaikkien valinnaisten parametrien on oltava funktion parametrien lopussa, jotta on selvää, mitä funktiolle annetut parametrit tarkoittavat.

Globaalit muuttujat

Funktiossa ovat oletuksena käytössä vain muuttujat, joille on annettu arvo funktion sisällä. Esimerkiksi seuraava koodi ei tulosta lukua 5, koska muuttuja $luku ei ole käytössä funktion sisällä:

<?php
function testi() {
    echo $luku;
}

$luku = 5;
testi();
?>

Jos ulkopuolista muuttujaa haluaa käyttää funktion sisällä, muuttuja täytyy määritellä globaaliksi sanalla global. Seuraava koodi tulostaa halutusti luvun 5:

<?php
function testi() {
    global $luku;
    echo $luku;
}

$luku = 5;
testi();
?>

Staattiset muuttujat

Tavallisesti kaikki funktion muuttujat häviävät, kun funktion suoritus päättyy. Jos muuttujan haluaa säilyvän kerrasta toiseen, muuttuja täytyy määritellä staattiseksi sanalla static. Seuraava koodi tulostaa ensin 1, sitten 2 ja lopuksi 3:

<?php
function testi() {
    static $luku = 1;
    echo $luku;
    $luku++;
}

testi();
testi();
testi();
?>

Funktioiden hyöty

Funktioista on kahdenlaista hyötyä ohjelmoinnissa:

Jos koodissa esiintyy monta kertaa käytännössä samanlainen osa, siitä kannattaa usein tehdä funktio, jolloin samanlainen koodi tarvitsee kirjoittaa vain kerran. Tällöin koodin pituus lyhenee ja jos funktioon tulee muutoksia, muutos riittää tehdä yhteen paikkaan koodissa.

Toisaalta funktioiden käyttäminen selventää usein koodia. Jos pitkä koodi on toteutettu ilman funktioita, se on helposti sekava ja koodin yleisrakennetta on vaikeaa hahmottaa. Jakamalla koodi pienempiin funktioihin se pysyy paremmin hallinnassa.


Kommentit

latenleffahylly [17.10.2012 22:19:07]

Lainaa #

Ostin iPadiin noin 50€ maksavan kirjan PHP:stä. Funktioiden kohdalla esimerkit olivat käsittämättömiä verrattuna tähän häkellyttävän hienosti tehtyyn funktio oppaaseen.

Uusi koodari älä huoli jos opas ei aukea ekalla tai tokalla kertaa. Opettele perusteet, palaa sitten tähän oppaaseen ja mieti miten käyttäisit näitä malleja omassa projektissasi. Funktiokirjaston rakentaminen olisi myös mukava lisä, mutta toisaalta turha mennä asioiden edelle, kiitos upeasta oppaasta ja ihmeen korkeasta tasosta joka säilyy oppaita sellaillessa. Ohjelmointiputkan hyöty funktioita opetellessa on korvaamaton, tämä laittaa miettimään. Missä ja miten funktiot olisivat auenneet näin jos ei tällä sivulla.

jsinkko [26.09.2016 18:04:43]

Lainaa #

Sen verran tuohon voisi lisätä, että nuo funktioiden parametrit ovat oletusarvoisesti value-tyyppisiä, eli kutsuvasta paikasta annettava parametrin arvo kopioidaan parametrin arvoksi.

Referenssityyppisten arvojen käyttö on myös mahdollista. Tällöin funktio in muotoa

function phpfunktio(&$parametri) {
  $parametri="jotakin..."; // parametriä käytetään normaalin
                           // muuttujan tavoin, paitsi että muuttujaan
                           // tehdyt muutokset näkynät "kutsuvan"
                           // koodin muuttujassa.
}

Esim.

$kerrokset=50;

if (lisaakerros($kerrokset)==0) {
  echo "Onnistui. Kerroksia on nyt $kerrokset.";
} else {
  echo "Kerrosten lisääminen ei ole mahdollista.";
}

function lisaakerros(&$kerroslkm) {

  if ($kerroslkm >= 50) {
    return 1;
  } else {
    $kerroslkm++;
    return 0;
  }
}

Kirjoita kommentti

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.

Muista lukea keskustelun ohjeet.
Tietoa sivustosta