익명 함수
closures
라고도 하는 익명 함수를 사용하면 지정된 이름이 없는 함수를 만들 수 있습니다. 호출 가능한 매개변수의 값으로 가장 유용하지만 다른 용도로 많이 사용됩니다.
익명 함수는 Closure 클래스를 사용하여 구현됩니다.
예제 #1 익명 함수 예
<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// outputs helloWorld
?>
클로저는 변수 값으로 사용할 수도 있습니다. PHP는 이러한 표현식을 자동으로 Closure 내부 클래스의 인스턴스로 변환합니다. 변수에 클로저를 할당하는 것은 후행 세미콜론을 포함하여 다른 할당과 동일한 구문을 사용합니다:
예제 #2 익명 함수 변수 할당 예
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
클로저는 부모 범위에서 변수를 상속할 수도 있습니다. 이러한 변수는 모두 use
언어 구성으로 전달되어야 합니다. PHP 7.1부터 이러한 변수에는 슈퍼글로벌, $this 또는 매개변수와 이름이 같은 변수가 포함되어서는 안 됩니다. 함수의 반환 유형 선언은 use
절 뒤에 위치해야 합니다.
예제 #3 상위 범위에서 변수 상속
<?php
$message = 'hello';
// No "use"
$example = function () {
var_dump($message);
};
$example();
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
$example();
// Inherited variable's value is from when the function
// is defined, not when called
$message = 'world';
$example();
// Reset message
$message = 'hello';
// Inherit by-reference
$example = function () use (&$message) {
var_dump($message);
};
$example();
// The changed value in the parent scope
// is reflected inside the function call
$message = 'world';
$example();
// Closures can also accept regular arguments
$example = function ($arg) use ($message) {
var_dump($arg . ' ' . $message);
};
$example("hello");
// Return type declaration comes after the use clause
$example = function () use ($message): string {
return "hello $message";
};
var_dump($example());
?>
위의 예는 다음과 유사한 결과를 출력합니다.
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"
PHP 8.0.0부터 범위 상속 변수 목록에 뒤에 오는 쉼표가 포함될 수 있으며 이는 무시됩니다.
상위 범위에서 변수를 상속하는 것은 전역 변수를 사용하는 것과 다릅니다. 전역 변수는 전역 범위에 존재하며, 이는 어떤 함수를 실행하든 동일합니다. 클로저의 상위 범위는 클로저가 선언된 함수입니다(반드시 호출된 함수는 아님). 다음 예를 참조하십시오.
예제 #4 클로저 및 범위
<?php
// A basic shopping cart which contains a list of added products
// and the quantity of each product. Includes a method which
// calculates the total price of the items in the cart using a
// closure as a 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;
// Add some items to the cart
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
// Print the total with a 5% sales tax.
print $my_cart->getTotal(0.05) . "\n";
// The result is 54.29
?>
예제 #5 $this의 자동 바인딩
<?php
class Test
{
public function testing()
{
return function() {
var_dump($this);
};
}
}
$object = new Test;
$function = $object->testing();
$function();
?>
위의 예는 다음을 출력합니다.
object(Test)#1 (0) { }
클래스 컨텍스트에서 선언되면 현재 클래스가 자동으로 바인딩되어 함수 범위 내에서 $this
를 사용할 수 있습니다. 현재 클래스의 이 자동 바인딩을 원하지 않으면 정적 익명 함수를 대신 사용할 수 있습니다.
정적 익명 함수
익명 함수는 정적으로 선언될 수 있습니다. 이렇게 하면 현재 클래스가 자동으로 바인딩되는 것을 방지할 수 있습니다. 개체는 런타임에 개체에 바인딩되지 않을 수도 있습니다.
예제 #6 정적 익명 함수 내에서 $this
사용 시도
<?php
class Foo
{
function __construct()
{
$func = static function() {
var_dump($this);
};
$func();
}
};
new Foo();
?>
위의 예는 다음을 출력합니다.
Notice: Undefined variable: this in %s on line %d NULL
예제 #7 정적 익명 함수에 개체 바인딩 시도
<?php
$func = static function() {
// function body
};
$func = $func->bindTo(new StdClass);
$func();
?>
위의 예는 다음을 출력합니다.
Warning: Cannot bind an instance to a static closure in %s on line %d
변경 로그
Version | Description |
---|---|
7.1.0 | 익명 함수는 슈퍼글로벌, $this 또는 매개변수와 이름이 같은 변수에 대해 닫을 수 없습니다. |
노트
참고: 클로저 내에서 func_num_args(), func_get_arg() 및 func_get_args()를 사용할 수 있습니다.