← Tilbage til koncepter

Closures & Anonymous Functions

Anonymous functions, closures, arrow functions og callback patterns i moderne PHP

Kategori: Fundamentals

🎯 Key Points

  • Anonymous functions - Funktioner uden navn der kan assignes til variabler
  • use keyword - Capture (inherit) variabler fra parent scope til closure
  • Arrow functions (fn) - Kort syntaks med implicit variable binding fra PHP 7.4
  • First-class functions - Funktioner kan passes som argumenter og returneres fra andre funktioner
  • Closure::bind() - Bind closure til specifik object scope og class context
  • Callbacks - Brug closures som callbacks i array_map, array_filter, usort etc
  • Variable scope - Closures har deres egen scope men kan access parent scope via use
  • By reference capture - Brug use (&$var) til at modificere parent scope variabler
  • Callable type hint - Type hint parameters som callable for at acceptere closures
  • Dependency injection - Brug closures til lazy loading af dependencies i containers
  • Higher-order functions - Funktioner der tager eller returnerer andre funktioner
  • Immutable by default - Captured variabler er by value unless explicitly by reference

💻 Kode Eksempel

<?php

// Basic closure with use keyword
$taxRate = 0.25;
$calculatePrice = function(float $amount) use ($taxRate): float {
    return $amount * (1 + $taxRate);
};

echo "Price with tax: " . $calculatePrice(100) . "\n";

// By-reference capture
$counter = 0;
$increment = function() use (&$counter): int {
    return ++$counter;
};

echo "Count: {$increment()}\n"; // 1
echo "Count: {$increment()}\n"; // 2
echo "Count: {$increment()}\n"; // 3

// Arrow functions (PHP 7.4+)
$numbers = [1, 2, 3, 4, 5];
$multiplier = 3;

$result = array_map(
    fn($n) => $n * $multiplier, // Implicit use of $multiplier
    $numbers
);
print_r($result);

// Higher-order functions
function createMultiplier(int $factor): Closure {
    return fn(int $x) => $x * $factor;
}

$double = createMultiplier(2);
$triple = createMultiplier(3);

echo "Double 10: {$double(10)}\n";
echo "Triple 10: {$triple(10)}\n";

// Closure binding to object scope
class User {
    private string $name = 'John Doe';
}

$user = new User();
$getName = function() {
    return $this->name; // Access private property
};

$boundClosure = Closure::bind($getName, $user, User::class);
echo "User name: {$boundClosure()}\n";

// Array operations with closures
$products = [
    ['name' => 'Laptop', 'price' => 1000],
    ['name' => 'Mouse', 'price' => 25],
    ['name' => 'Keyboard', 'price' => 75],
];

// Filter products over 50
$expensive = array_filter(
    $products,
    fn($p) => $p['price'] > 50
);

// Sort by price
usort($products, fn($a, $b) => $a['price'] <=> $b['price']);

// Calculate total
$total = array_reduce(
    $products,
    fn($sum, $p) => $sum + $p['price'],
    0
);

echo "Total price: {$total}\n";

💼 Hvornår bruges det?

  • Array transformations med array_map, array_filter og array_reduce for data processing pipelines
  • Event handlers og callbacks i event-driven arkitekturer og observer patterns
  • Dependency injection containers hvor services lazy-loades via closures (Laravel service providers)
  • Route definitions i web frameworks hvor hver route handler er en closure (Laravel, Slim)
  • Database query builders med dynamic where clauses som closures (Eloquent, Doctrine)
  • Middleware pipelines hvor hver middleware layer er implementeret som closure

⭐ Best Practices

  • Prefer arrow functions (fn) for simple one-liner callbacks - mere læsbar og koncis
  • Brug use keyword eksplicit for bedre readability - gør det klart hvilke variabler der captures
  • Undgå for mange captured variabler - hvis closure bruger > 3 variabler, overvej class method
  • Type hint callable parameters og return types for bedre IDE support og type safety
  • Brug by-reference capture (&$var) sparsomt - kan føre til unexpected side effects
  • Dokumentér closures med PHPDoc @var annotations når type ikke er obvious
  • Hold closures små og fokuserede - split komplekse closures i multiple named functions
  • Vær opmærksom på memory leaks - closures holder references til captured variabler

ℹ️ Quick Info

Kategori
Fundamentals
Sværhedsgrad
Mellem