Anonyma funktioner

Från Wiki.linux.se
Hoppa till navigering Hoppa till sök

Anonyma funktioner

Anonyma funktioner, även kända som closures, tillåter skapandet av funktioner som inte har något specificerat namn. De är mest användbara som värdet för callable-parametrar, men de har många andra användningsområden.

Anonyma funktioner implementeras med hjälp av klassen Closure.

Exempel #1 Exempel på anonym funktion

<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world');
// skriver ut helloWorld
?>

Closures kan också användas som värden för variabler; PHP konverterar automatiskt sådana uttryck till instanser av den interna klassen Closure. Tilldelning av en closure till en variabel använder samma syntax som för andra tilldelningar, inklusive avslutande semikolon:

Exempel #2 Exempel på tilldelning av anonym funktion till en variabel

<?php
$greet = function($name) {
    printf("Hello %s\r\n", $name);
};

$greet('World');
$greet('PHP');
?>

Closures kan också ärva variabler från det överordnade omfånget. Alla sådana variabler måste skickas till språkkonstruktionen use. Från och med PHP 7.1 får dessa variabler inte inkludera superglobals, $this, eller variabler med samma namn som en parameter. En returtypdeklaration för funktionen måste placeras efter use-klasulen.

Exempel #3 Ärva variabler från det överordnade omfånget

<?php
$message = 'hello';

// Ingen "use"
$example = function () {
    var_dump($message);
};
$example();

// Ärva $message
$example = function () use ($message) {
    var_dump($message);
};
$example();

// Det ärvda värdet för variabeln är från när funktionen
// definierades, inte när den anropades
$message = 'world';
$example();

// Återställ message
$message = 'hello';

// Ärva genom referens
$example = function () use (&$message) {
    var_dump($message);
};
$example();

// Den ändrade värdet i det överordnade omfånget
// återspeglas inuti funktionsanropet
$message = 'world';
$example();

// Closures kan också acceptera vanliga argument
$example = function ($arg) use ($message) {
    var_dump($arg . ' ' . $message);
};
$example("hello");

// Returtypdeklaration kommer efter use-klasulen
$example = function () use ($message): string {
    return "hello $message";
};
var_dump($example());
?>

Ovanstående exempel kommer att ge något liknande:

Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hello"
string(5) "hello"
string(5) "hello"
string(5) "world"
string(11) "hello world"
string(11) "hello world"

Från och med PHP 8.0.0 kan listan över ärvda variabler innehålla ett avslutande komma, vilket kommer att ignoreras.

Att ärva variabler från det överordnade omfånget är inte samma sak som att använda globala variabler. Globala variabler existerar i det globala omfånget, vilket är detsamma oavsett vilken funktion som exekveras. Det överordnade omfånget för en closure är den funktion där closuren deklarerades (inte nödvändigtvis den funktion där den anropades). Se följande exempel:

Exempel #4 Closures och omfång

<?php
// En grundläggande varukorg som innehåller en lista över tillagda produkter
// och antalet av varje produkt. Inkluderar en metod som
// beräknar det totala priset för artiklarna i varukorgen med en
// closure som en callback.
class Cart
{
    const PRICE_BUTTER  = 1.00;
    const PRICE_MILK    = 3.00;
    const PRICE_EGGS    = 6.95;

    protected $products = array();
    
    public function add($product, $quantity)
    {
        $this->products[$product] = $quantity;
    }
    
    public function getQuantity($product)
    {
        return isset($this->products[$product]) ? $this->products[$product] :
               FALSE;
    }
    
    public function getTotal($tax)
    {
        $total = 0.00;
        
        $callback =
            function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };
        
        array_walk($this->products, $callback);
        return round($total, 2);
    }
}

$my_cart = new Cart;

// Lägg till några artiklar i varukorgen
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);

// Skriv ut totalen med 5% moms.
print $my_cart->getTotal(0.05) . "\n";
// Resultatet är 54.29
?>

Exempel #5 Automatisk bindning av $this

<?php

class Test
{
    public function testing()
    {
        return function() {
            var_dump($this);
        };
    }
}

$object = new Test;
$function = $object->testing();
$function();
    
?>

Ovanstående exempel kommer att ge:

object(Test)#1 (0) {
}

När en anonym funktion deklareras i kontexten av en klass, binds den aktuella klassen automatiskt till den, vilket gör $this tillgänglig inuti funktionens omfång. Om denna automatiska bindning av den aktuella klassen inte önskas, kan statiska anonyma funktioner istället användas.

Statiska anonyma funktioner

Anonyma funktioner kan deklareras som statiska. Detta förhindrar att den aktuella klassen automatiskt binds till dem. Objekt kan inte heller bindas till dem vid körning.

Exempel #6 Försök att använda $this inuti en statisk anonym funktion

<?php

class Foo
{
    function __construct()
    {
        $func = static function() {
            var_dump($this);
        };
        $func();
    }
};
new Foo();

?>

Ovanstående exempel kommer att ge:

Notice: Undefined variable: this in %s on line %d
NULL

Exempel #7 Försök att binda ett objekt till en statisk anonym funktion

<?php

$func = static function() {
    // funktionskropp
};
$func = $func->bindTo(new stdClass);
$func();

?>

Ovanstående exempel kommer att ge:

Warning: Cannot bind an instance to a static closure in %s on line %d

Ändringslogg

Version
Beskrivning
7.1.0
Anonyma funktioner kan inte stänga över superglobals, $this, eller någon variabel med samma namn som en parameter.

Anmärkningar

Notera: Det är möjligt att använda func_num_args(), func_get_arg(), och func_get_args() inuti en closure.

Sidslut

Orginalhemsidan på Engelska :
PHP
Språkreferens
Språkreferens#Funktioner