>백엔드 개발 >PHP 튜토리얼 >PHP 클로저 및 Course 클래스 메소드의 기능 분석

PHP 클로저 및 Course 클래스 메소드의 기능 분석

藏色散人
藏色散人앞으로
2022-02-05 04:00:324735검색

PHP Clouse(클로저 클래스) 간략한 분석

0x00 서문

클로저란 생성 시 주변 상태를 캡슐화하는 함수를 말합니다. 클로저가 위치한 환경이 더 이상 존재하지 않더라도 클로저에 캡슐화된 상태는 여전히 존재합니다.

PHP의 모든 클로저는 Clorse 클래스에 의해 인스턴스화되는 객체입니다. 즉, 클로저는 다른 PHP 객체와 다르지 않습니다. 객체에는 해당 메소드와 속성이 있어야 합니다. 이 기사에서는 PHP에서 클로저의 기본 사용법과 Clorse 클래스 메소드의 역할을 요약합니다. [추천: PHP 비디오 튜토리얼]

0x01 클로저의 기본 사용법

클로저의 가장 기본적인 사용법을 살펴보겠습니다:

<?php
$hello = function ($word) {
    return &#39;hello &#39; . $word;
};
echo $hello(&#39;world&#39;);
// 输出 hello world

이 코드의 가장 직관적인 느낌은 다음에 함수를 할당하는 것입니다. $hello 변수를 선택한 다음 $hello를 통해 직접 호출합니다. 하지만 이 클로저는 상위 범위에서 변수를 상속하지 않습니다(즉, 주변 상태를 캡슐화합니다). use 키워드를 통해 클로저의 상위 범위에서 변수를 상속할 수 있습니다. 예는 다음과 같습니다:

<?php
$name = &#39;panda&#39;;
$hello = function () use ($name) {
    return &#39;hello &#39; . $name;
};
echo $hello();
// 输出 hello panda

PHP 7.1부터 사용은 superglobals, $this 또는 매개변수와 동일한 이름을 갖는 변수를 전달할 수 없습니다.

또한 use 키워드를 사용하면 상위 범위의 변수가 값으로 클로저에 전달됩니다. 즉, 클로저가 생성되면 외부 변수가 수정되더라도 클로저에 전달된 값에는 영향을 미치지 않습니다. 폐쇄는 여전히 존재합니다). 예는 다음과 같습니다:

<?php
$name = &#39;panda&#39;;
$hello = function () use ($name) {
    return &#39;hello &#39; . $name;
};
$name = &#39;cat&#39;;
echo $hello();
// 输出 hello panda

변수에 대한 참조를 전달하면 클로저가 외부 변수의 값을 수정할 수 있습니다. 예는 다음과 같습니다.

<?php
$name = &#39;panda&#39;;
$changeName = function () use (&$name) {
    $name = &#39;cat&#39;;
};
$changeName();
echo $name;
// 输出 cat

참고: PHP에서 객체를 전달할 때 기본값은 전달입니다. 참조로 사용하므로 클로저 내에서 사용하여 전달된 객체를 조작할 때는 특별한 주의가 필요합니다. 예는 다음과 같습니다:

<?php
class Dog {
    public $name = &#39;Wang Cai&#39;;
}
$dog = new Dog();
$changeName = function () use ($dog) {
    $dog->name = &#39;Lai Fu&#39;;
};
$changeName();
echo $dog->name;
// 输出 Lai Fu

0x02 클로저 클래스

클로저가 단지 클로저 클래스 객체임을 증명

<?php
$clourse = function () {
    echo &#39;hello clourse&#39;;
};
if (is_object($clourse)) {
    echo get_class($clourse);
}
// 输出 Closure

위 코드는 클로저가 단지 일반적인 클로저 클래스 객체임을 증명하는 Closure를 출력합니다.

Clouse 클래스 요약

PHP 공식 매뉴얼에서 클로저 클래스에 대한 관련 정보를 확인할 수 있습니다. 다음은 PhpStorm의 로컬 문서에서 본 Clouse 클래스의 요약입니다.

/**
 * Class used to represent anonymous functions.
 * <p>Anonymous functions, implemented in PHP 5.3, yield objects of this type.
 * This fact used to be considered an implementation detail, but it can now be relied upon.
 * Starting with PHP 5.4, this class has methods that allow further control of the anonymous function after it has been created.
 * <p>Besides the methods listed here, this class also has an __invoke method.
 * This is for consistency with other classes that implement calling magic, as this method is not used for calling the function.
 * @link http://www.php.net/manual/en/class.closure.php
 */
final class Closure {
    /**
     * This method exists only to disallow instantiation of the Closure class.
     * Objects of this class are created in the fashion described on the anonymous functions page.
     * @link http://www.php.net/manual/en/closure.construct.php
     */
    private function __construct() { }
    /**
     * This is for consistency with other classes that implement calling magic,
     * as this method is not used for calling the function.
     * @param mixed $_ [optional]
     * @return mixed
     * @link http://www.php.net/manual/en/class.closure.php
     */
    public function __invoke(...$_) { }
    /**
     * Duplicates the closure with a new bound object and class scope
     * @link http://www.php.net/manual/en/closure.bindto.php
     * @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
     * @param mixed $newscope The class scope to which associate the closure is to be associated, or &#39;static&#39; to keep the current one.
     * If an object is given, the type of the object will be used instead.
     * This determines the visibility of protected and private methods of the bound object.
     * @return Closure Returns the newly created Closure object or FALSE on failure
     */
    function bindTo($newthis, $newscope = &#39;static&#39;) { }
    /**
     * This method is a static version of Closure::bindTo().
     * See the documentation of that method for more information.
     * @static
     * @link http://www.php.net/manual/en/closure.bind.php
     * @param Closure $closure The anonymous functions to bind.
     * @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
     * @param mixed $newscope The class scope to which associate the closure is to be associated, or &#39;static&#39; to keep the current one.
     * If an object is given, the type of the object will be used instead.
     * This determines the visibility of protected and private methods of the bound object.
     * @return Closure Returns the newly created Closure object or FALSE on failure
     */
    static function bind(Closure $closure, $newthis, $newscope = &#39;static&#39;) { }
    /**
     * Temporarily binds the closure to newthis, and calls it with any given parameters.
     * @link http://php.net/manual/en/closure.call.php
     * @param object $newThis The object to bind the closure to for the duration of the call.
     * @param mixed $parameters [optional] Zero or more parameters, which will be given as parameters to the closure.
     * @return mixed
     * @since 7.0
     */
    function call ($newThis, ...$parameters) {}
    
    /**
     * @param callable $callable
     * @return Closure
     * @since 7.1
     */
    public static function fromCallable (callable $callable) {}
}

우선, Clorse 클래스는 상속될 수 없다는 것을 의미합니다. 둘째, 생성자 __construct는 private으로 설정됩니다. 이는 클로저 객체가 new 키워드를 통해 인스턴스화될 수 없음을 의미합니다. 클로저만 구문 함수 (...) use(...) {...}를 통해서만 인스턴스화할 수 있는지 확인하십시오.

클로저를 함수로 실행할 수 있는 이유는 무엇인가요?

위 클래스 요약을 보면 Clorse 클래스가 __invoke 메소드를 구현한 것을 알 수 있습니다. 해당 메소드는 공식 PHP 매뉴얼에 다음과 같이 설명되어 있습니다.

함수를 호출하여 객체를 호출하려고 하면 __invoke() 메소드 will이 자동으로 호출됩니다.

이것이 클로저가 함수로 실행될 수 있는 이유입니다.

지정된 $this 객체와 클래스 범위를 바인딩합니다

클로저 라우팅 사용을 허용하는 프레임워크(예: Slim)에서 다음과 같은 내용을 볼 수 있습니다.

$app->get(&#39;/test&#39;, function () {
    echo $this->request->getMethod();
});

이 클로저에서 $를 실제로 사용할 수 있나요? $this가 가리키는 객체는 무엇인가요?

$this를 클래스 범위에 바인딩하는 기능은 바인딩To 및 바인딩 메서드를 통해 수행할 수 있습니다. 예는 다음과 같습니다.

<?php
class Pandas {
    public $num = 1;
}
$pandas = new Pandas();
$add = function () {
    echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas);
$newAdd1();
// 输出 2
$newAdd2 = Closure::bind($add, $pandas);
$newAdd2();
// 输出 3

위 예는 지정된 개체를 클로저의 $this에 바인딩하지만 우리는 그렇지 않습니다. 클래스 범위를 지정합니다. 따라서 Pandas 클래스의 $num 속성을 protected 또는 private으로 다시 작성하면 치명적인 오류가 발생합니다!

Fatal error: Uncaught Error: Cannot access protected property Pandas::$num

바인딩된 개체의 비공개 속성이나 메서드에 액세스해야 하는 경우 클래스 범위를 지정해야 합니다. 예는 다음과 같습니다.

<?php
class Pandas {
    protected $num = 1;
}
$pandas = new Pandas();
$add = function () {
    echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas, $pandas);
$newAdd1();
// 输出 2
$newAdd2 = Closure::bind($add, $pandas, &#39;Pandas&#39;);
$newAdd2();
// 输出 3

여기서 우리는 binTo 및 바인딩 메서드 모두 $newscope를 지정하는 것을 볼 수 있습니다. $newscope 매개변수의 기본값은 static입니다. 즉, 클래스 범위는 변경되지 않습니다. $newscope 매개변수는 클래스 이름이나 객체를 받아 클로저의 클래스 범위를 지정된 클래스 범위로 변경합니다. 이때 클로저에서 Pandas 클래스의 $num 속성에 접근할 수 있습니다.

$this 개체와 클래스 범위를 한 번에 바인딩하고 실행합니다(PHP7).

bindTo 및 바인딩 메서드는 새 개체 및 클래스 범위 패키지가 지정될 때마다 원래 클로저를 복사하고 새 클로저를 반환해야 합니다. 바인딩된 개체를 여러 번 수정해야 하는 경우 번거롭기 때문에 PHP7은 클로저를 개체(클래스 범위도 해당 개체가 속한 개체로 수정됨)에 일시적으로 바인딩하고 실행할 수 있는 새로운 메서드 호출을 제공합니다.

<?php
class Pandas {
    protected $num = 1;
}
$pandas = new Pandas();
$add = function ($num) {
    $this->num += $num;
    echo $this->num . PHP_EOL;
};
$add->call($pandas, 5);
// 输出 6

Callable to closure (PHP7.1)

PHP7.1에서 Closure 클래스에는 호출 가능 유형 값을 클로저로 변환할 수 있는 fromCallable 메서드가 있습니다.

<?php
class Foo
{
    protected $num = 1;
    public static function hello(string $bar)
    {
        echo &#39;hello &#39; . $bar;
    }
}
$hello = Closure::fromCallable([&#39;Foo&#39;, &#39;hello&#39;]);
$hello(&#39;world&#39;);

이런 작성 방법이 꽤 멋지군요. 결국 클로저를 통해 호출하는 것이 call_user_func 함수를 사용하는 것보다 훨씬 더 재미있습니다.

0x03 요약

자세한 내용은 Closure 클래스 및 익명 함수를 참조하세요. PHP 공식 매뉴얼의 Closure 클래스 중국어 버전은 업데이트되지 않았기 때문에 call 및 fromCallable 메서드에 대한 내용이 없습니다. . 영문판(ㄒoㄒ)을 읽어보시길 권합니다.

위 내용은 PHP 클로저 및 Course 클래스 메소드의 기능 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제