Functies en scope in PHP: uitleg met voorbeelden

Leer hoe functies en scope in PHP werken. Praktische uitleg over parameters, return values, global/local scope en closures voor developers.

5 juni 20267 min leestijdDoor We Develop Communication

Functies en scope in PHP zijn twee van de belangrijkste concepten die je onder de knie moet krijgen voordat je serieuze applicaties gaat bouwen. Ze bepalen hoe je code georganiseerd blijft, hoe je herhaling voorkomt en hoe variabelen zich gedragen binnen verschillende delen van je programma.

In eerdere delen van deze serie hebben we gekeken naar variabelen, types en control flow en arrays en loops. Het is tijd om die kennis samen te brengen in een krachtiger concept: herbruikbare blokken code met duidelijke grenzen.

In dit artikel leer je hoe je functies definieert, welke scope-regels PHP hanteert, hoe parameters en return values werken, en waarom closures en type declarations in moderne PHP onmisbaar zijn geworden.

Waarom functies?

Stel je voor dat je op tien plekken in je applicatie een bedrag moet omrekenen naar een prijs inclusief btw. Zonder functies kopieer je dezelfde berekening overal. Verandert het btw-tarief, dan mag je tien plekken aanpassen. Met een functie schrijf je de logica één keer op en roep je die aan waar nodig.

Functies geven je drie voordelen in één keer:

  • Herbruikbaarheid: eenmaal schrijven, overal gebruiken.
  • Leesbaarheid: een goed benoemde functie vertelt wat er gebeurt.
  • Onderhoudbaarheid: wijzigingen op één plek werken overal door.

Dit principe heet DRY (Don't Repeat Yourself) en is een van de pijlers van schone code.

Een functie definiëren

De basissyntax van een PHP-functie ziet er zo uit:

function begroet($naam) {
    return "Hallo, {$naam}!";
}

echo begroet('Sander'); // Hallo, Sander!

Je gebruikt het keyword function, gevolgd door een naam, parameters tussen haakjes en een code-block tussen accolades. Met return geef je een waarde terug aan de aanroeper.

Functienamen zijn in PHP niet hoofdlettergevoelig, maar schrijf ze altijd consistent (meestal camelCase of snake_case, afhankelijk van de codebase).

Parameters en standaardwaarden

Je kunt parameters een standaardwaarde meegeven, zodat ze optioneel worden:

function begroet($naam, $taal = 'nl') {
    return $taal === 'nl' ? "Hallo {$naam}" : "Hello {$naam}";
}

echo begroet('Sander');          // Hallo Sander
echo begroet('Sander', 'en');    // Hello Sander

Parameters met een standaardwaarde moeten altijd na verplichte parameters staan.

Named arguments (PHP 8+)

Sinds PHP 8 kun je parameters bij naam doorgeven, wat handig is bij functies met veel optionele waarden:

function maakGebruiker(string $naam, string $rol = 'user', bool $actief = true) {
    // ...
}

maakGebruiker(naam: 'Sander', actief: false);

Dit maakt je code leesbaarder en voorkomt fouten bij functies met lange parameterlijsten.

Type declarations en return types

Moderne PHP is typesafe(r) dan je misschien denkt. Je kunt types aangeven voor parameters en return values:

declare(strict_types=1);

function vermenigvuldig(int $a, int $b): int {
    return $a * $b;
}

echo vermenigvuldig(3, 4); // 12

Met declare(strict_types=1) bovenaan je bestand dwing je PHP om strikt te controleren. Geef je een string mee aan een parameter die een int verwacht, dan krijg je een TypeError.

Ondersteunde types zijn onder andere: int, float, string, bool, array, object, callable, iterable, klassenamen, void, never, en union types zoals int|string.

Gebruik type declarations zoveel mogelijk, ze vangen bugs vroeg af en maken de intentie van je code duidelijk. De officiële PHP-documentatie over type declarations geeft een uitgebreid overzicht.

Scope in PHP: local vs global

Hier wordt het interessant. In PHP hebben variabelen een scope: het gebied waarin ze bestaan en toegankelijk zijn.

$naam = 'Sander';

function zegHallo() {
    echo "Hallo, {$naam}!"; // Foutmelding: $naam is undefined
}

zegHallo();

Verrassend? PHP isoleert functies standaard. De variabele $naam bestaat buiten de functie, maar is binnen de functie onbekend. Dit is bewust zo ontworpen: het voorkomt dat functies per ongeluk globale state wijzigen.

De global-keyword (gebruik met mate)

Wil je toch bij een globale variabele, dan kun je de global-keyword gebruiken:

$teller = 0;

function tikAan() {
    global $teller;
    $teller++;
}

tikAan();
tikAan();
echo $teller; // 2

Let op: gebruik global zo min mogelijk. Het maakt je code moeilijker te testen en te begrijpen, omdat functies niet meer zelfstandig zijn. Een betere oplossing is om de waarde als parameter mee te geven of in een object te verpakken.

De superglobals

Er zijn speciale arrays die overal beschikbaar zijn, zonder global-keyword:

  • $_GET, $_POST, $_REQUEST, data uit HTTP-requests
  • $_SESSION, $_COOKIE, sessies en cookies
  • $_SERVER, $_ENV, server- en omgevingsvariabelen
  • $_FILES, geüploade bestanden

Deze superglobals zijn de uitzondering op de scope-regel en zijn altijd binnen functies bruikbaar.

Parameters: by value vs by reference

Standaard geeft PHP parameters door by value: de functie werkt met een kopie.

function verdubbel($x) {
    $x = $x * 2;
}

$getal = 5;
verdubbel($getal);
echo $getal; // 5, niet 10

Wil je dat een functie de originele variabele wijzigt, gebruik dan een ampersand (&) om door te geven by reference:

function verdubbel(&$x) {
    $x = $x * 2;
}

$getal = 5;
verdubbel($getal);
echo $getal; // 10

Gebruik references bewust. Ze maken code krachtig, maar ook minder voorspelbaar. Voor de meeste use cases is het cleaner om een nieuwe waarde te retourneren en die toe te wijzen.

Variadische functies

Soms weet je niet precies hoeveel argumenten een functie krijgt. Dan is de spread-operator (...) handig:

function telAlles(int ...$getallen): int {
    return array_sum($getallen);
}

echo telAlles(1, 2, 3);        // 6
echo telAlles(5, 10, 15, 20);  // 50

Binnen de functie is $getallen een array met alle meegegeven waarden. Je kunt de spread-operator ook gebruiken om een array uit te pakken als argumenten:

$cijfers = [1, 2, 3, 4];
echo telAlles(...$cijfers); // 10

Anonieme functies en closures

Een anonieme functie (ook wel closure) is een functie zonder naam die je aan een variabele kunt toekennen of direct doorgeven als callback:

$kwadraat = function(int $n): int {
    return $n * $n;
};

echo $kwadraat(5); // 25

Closures worden veel gebruikt met array-functies:

$getallen = [1, 2, 3, 4, 5];
$verdubbeld = array_map(fn($n) => $n * 2, $getallen);
// [2, 4, 6, 8, 10]

De fn(...) => syntax is een arrow function (PHP 7.4+). Arrow functions zijn compacter en leggen automatisch variabelen uit de omliggende scope vast.

De use-keyword

Gewone closures zien de buitenstaande scope niet automatisch. Met use kun je variabelen expliciet binnenhalen:

$prefix = 'Dhr. ';

$metPrefix = function(string $naam) use ($prefix): string {
    return $prefix . $naam;
};

echo $metPrefix('Van der Burgt'); // Dhr. Van der Burgt

Arrow functions hebben dit niet nodig, ze erven de scope automatisch, maar zijn beperkt tot één expressie.

First-class callable syntax (PHP 8.1+)

Sinds PHP 8.1 kun je een functie of methode heel elegant als callable doorgeven:

$upper = strtoupper(...);
echo $upper('hallo'); // HALLO

$namen = ['sander', 'jan', 'piet'];
$geupper = array_map(strtoupper(...), $namen);

Dit is vaak schoner dan een closure omheen te bouwen.

Best practices voor functies

Enkele vuistregels die je meteen kunt toepassen:

  1. Eén functie, één verantwoordelijkheid: een functie die zowel data ophaalt, valideert én mailt is te groot. Splits op.
  2. Beschrijvende namen: berekenBtw() zegt meer dan calc().
  3. Gebruik type declarations: voor parameters én return types.
  4. Vermijd te veel parameters: meer dan 4 parameters is een signaal dat je een object of array met opties moet overwegen.
  5. Return vroeg: gebruik guard clauses om nesting te beperken.
  6. Vermijd side effects: een functie die alleen een waarde teruggeeft op basis van input is voorspelbaar en testbaar.
// Minder goed
function verwerk($user) {
    if ($user !== null) {
        if ($user->actief) {
            // diepe nesting...
        }
    }
}

// Beter
function verwerk(?User $user): void {
    if ($user === null) return;
    if (!$user->actief) return;
    
    // hoofdlogica zonder nesting
}

Voor een bredere kijk op schone code kun je PSR-12 van PHP-FIG raadplegen, de veelgebruikte coding style standard.

Recursieve functies

Een functie kan zichzelf aanroepen, dat heet recursie. Klassiek voorbeeld: faculteit.

function faculteit(int $n): int {
    if ($n <= 1) {
        return 1;
    }
    return $n * faculteit($n - 1);
}

echo faculteit(5); // 120

Zorg altijd voor een basisvoorwaarde (hier: $n <= 1) anders krijg je een stack overflow. Recursie is elegant voor problemen als directory-traversal, boomstructuren of mathematische reeksen.

Variabele functies

In PHP kun je een functienaam in een string opslaan en die aanroepen:

$actie = 'strtoupper';
echo $actie('hallo'); // HALLO

Dit wordt veel gebruikt in frameworks voor dispatching, maar wees voorzichtig: dynamische aanroepen maken code moeilijker te analyseren. De moderne first-class callable syntax is vaak te prefereren.

Veelgestelde vragen

Wat is een functie in PHP?

Een functie in PHP is een herbruikbaar blok code dat je kunt aanroepen met een naam. Functies nemen optioneel parameters aan en kunnen een waarde teruggeven met return. Ze helpen je om code te structureren en herhaling te voorkomen.

Wat is het verschil tussen local en global scope?

Local scope betekent dat een variabele alleen binnen de functie bestaat waar hij is gedefinieerd. Global scope verwijst naar variabelen buiten functies. PHP isoleert functies standaard, dus globale variabelen zijn binnen een functie niet automatisch beschikbaar.

Hoe geef ik parameters by reference mee in PHP?

Plaats een ampersand (&) voor de parameter in de functiedefinitie, bijvoorbeeld function increment(&$value). Wijzigingen binnen de functie werken dan door op de originele variabele buiten de functie. Gebruik dit bewust, want het maakt code moeilijker te volgen.

Wat is een closure in PHP?

Een closure is een anonieme functie die variabelen uit de omliggende scope kan vastleggen met de use-keyword. Closures zijn handig voor callbacks, array-functies en functionele programmeerstijlen. Sinds PHP 7.4 bestaan er ook arrow functions met een compactere syntax.

Moet ik altijd return types en type hints gebruiken?

Ja, in moderne PHP (7.4+ en zeker 8.x) worden type hints en return types sterk aanbevolen. Ze maken je code veiliger, beter leesbaar en helpen IDE's met autocomplete. Voor nieuwe projecten is strict_types declareren een goede standaard.

Samenvatting

Functies zijn de bouwstenen waarmee je grotere PHP-applicaties structureert. Door scope goed te begrijpen, voorkom je subtiele bugs met globale state. Type declarations, closures en moderne PHP 8-features maken je code tegelijk veiliger en expressiever.

Wil je weer even terug naar de basis? Bekijk dan ons artikel over PHP installatie en je eerste script of de uitleg over wat PHP eigenlijk is. In een volgend deel van deze serie duiken we in objectgeoriënteerd programmeren, waar functies evolueren tot methoden en scope een extra dimensie krijgt.

Veelgestelde vragen

Klaar om digitaal te groeien?

Wij helpen Nederlandse bedrijven met webtechnologie en SEO-strategieën die écht werken. Neem vrijblijvend contact op.