>  기사  >  백엔드 개발  >  PHP Closure 클래스와 그 사용법에 대한 간략한 토론

PHP Closure 클래스와 그 사용법에 대한 간략한 토론

青灯夜游
青灯夜游앞으로
2021-03-05 17:58:414826검색

이 기사에서는 PHP Closure 클래스와 Closure를 사용하여 익명 함수를 만드는 방법을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

PHP Closure 클래스와 그 사용법에 대한 간략한 토론

추천 학습: "PHP Video Tutorial"

Closure class

익명 함수를 나타내는 데 사용되는 클래스입니다.

익명 함수(PHP 5.3에 도입됨)는 이러한 유형의 객체를 생성합니다. 과거에는 이 클래스가 구현 세부 사항으로 간주되었지만 이제는 무언가를 수행하는 데 의존할 수 있습니다. PHP 5.4부터
이 클래스에는 익명 함수가 생성된 후 이를 더 효과적으로 제어할 수 있는 메서드가 제공됩니다.

이 클래스에는 인스턴스화할 수 없습니다. 둘 다 클로저를 복사하는 데 사용됩니다. 하나는 정적이고 하나는 동적입니다. 이해하기 어려운 두 가지 방법은 아래에 자세히 설명되어 있습니다.

Closure::bind

public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )

参数说明:
closure
需要绑定的匿名函数。

newthis
需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。

newscope
想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 
私有、保护方法 的可见性。 The class scope to which associate the closure is to be associated, or 'static' 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.

위는 이 메소드의 정의입니다. 첫 번째 매개변수는 이해하기 쉽지만, 두 번째 매개변수는 복사할 클로저에 다음과 같은 내용이 포함되어 있으면 이해하기 쉽지 않습니다. $this, 이 개체는 $this,这个对象就表示这个
$this,闭包函数里面对这个对象的修改在调用结束之后也会保持一致,比如修改了一个属性;第三个参数就不太好理解了,看官方的说明也是云里雾里的,
默认参数情况下,调用$this->访问object $newthis中的属性函数的时候,会有限制,只能访问public属性的函数,如果想访问protected/private属性,
就要设置为对应的类名/类实例,就要像在类里面一样,要访问那个类的保护/私有属性函数。

例子

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$test = new T();

$func = Closure::bind(function(){
    $this->who();
    $this->name();
    $this->show();
}, $test);

$func();

上面的代码会报错Fatal error: Uncaught Error: Call to protected method T::who() from  context 'Closure'。 加上bind第三个参数为t::class或者new T(),会正常输出每一个结果。

我是T里面的保护函数:who
我是T里面的公共函数:name
我是T里面的私有函数:show

当然了,闭包也可以传递参数

$test = new StdClass();
var_dump($test);

$func = Closure::bind(function($obj){
    $obj->name = "燕睿涛";
}, null);

$func($test);
var_dump($test);

上面的程序跟匿名函数一样,啥对象也没有依赖,上面的程序会输出:

object(stdClass)#1 (0) {
}
object(stdClass)#1 (1) {
  ["name"]=>
  string(9) "燕睿涛"
}

另外还有个特别要说明的例子

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = Closure::bind(function ($obj) {
    $obj->show();
}, null);

$test = new T();

$func($test);

上面的情况会输出什么呢,没错,会报错,提示访问不了私有属性show,这个时候,加上第三个参数就可以了,看了第三个参数不光影响$this的作用域,
也可以影响参数的作用域。

Closure::bindTo

bindTobind功能类似,这里只是另外一种形式,都是复制当前闭包对象,绑定指定的$this对象和类作用域。,参数比bind少了第一个,
后面两个一样,当然还有一个区别就是bindTo不是静态方法,是闭包才会存在的一个属性方法。

例子

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = function () {
    $this->show();
    $this->who();
    $this->name();
};

$funcNew = $func->bindTo(new T(), T::class);

$funcNew();

上面函数的输出和bind的类似

我是T里面的私有函数:show
我是T里面的保护函数:who
我是T里面的公共函数:name

一个trick

这个函数是在看composer生成的自动加载源码的时候碰到的,在composer中用的比较特别,下面是截取部分composer中的代码

// 文件autoload_real.php
call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer($loader));

// 文件autoload_static.php
public static function getInitializer(ClassLoader $loader)
{
    return \Closure::bind(function () use ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}

上面的代码比较奇特,在call_user_func中,第一感觉是传错参数了,其实不然,这里调用了一个函数,这个函数会返回一个Closure对象,
也就是一个匿名函数,最终传入的参数还是一个callable类型。再看看这个返回的闭包,里面使用了use$this를 나타냅니다. 클로저 함수에서 이 개체에 대한 수정은 속성 수정과 같이 호출이 완료된 후에도 일관되게 유지됩니다. 매개변수는 이해하기 쉽지 않습니다.
기본 매개변수를 사용하면 $newthis객체에 액세스하려면 $this->를 호출하세요. code>의 경우에는 public 속성이 있는 함수에만 접근할 수 있습니다. protected/private 속성에 접근하려면

를 해당 클래스 이름으로 설정해야 합니다. /class 인스턴스, 클래스와 마찬가지로 해당 클래스의 protected/private 속성 기능에 액세스해야 합니다.

Example

call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer(), $loader);

public static function getInitializer()
{
    return \Closure::bind(function ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}
위 코드는 오류를 보고합니다치명적인 오류: Uncaught Error: Call to protected method T::who() from context 'Closure'. <code>t::class 또는 new T()에 바인딩의 세 번째 매개변수를 추가하면 각 결과가 정상적으로 출력됩니다. rrreee물론 클로저도 매개변수를 전달할 수 있습니다

rrreee

위 프로그램은 익명 함수와 동일하며 어떤 객체에도 종속되지 않습니다. 위 프로그램은 다음을 출력합니다. 🎜rrreee🎜다음과 같은 특별한 예도 있습니다. be explain🎜rrreee🎜 위 상황에서 출력되는 내용은 무엇입니까? 예, 개인 속성인 show에 접근할 수 없다는 오류가 보고됩니다. 이 때 세 번째 매개변수만 추가하면 됩니다. 세 번째 매개변수를 읽으면 $this에 영향을 미칠 뿐만 아니라 🎜 매개변수 범위에도 영향을 미칠 수 있습니다. 🎜

🎜Closure::bindTo🎜🎜🎜bindTobind는 비슷한 기능을 가지고 있습니다. 여기에는 또 다른 형식이 있습니다. 둘 다 복사합니다. 현재 클로저 개체는 지정된 $this 개체 및 클래스 범위에 바인딩됩니다. 에서 첫 번째 매개변수는 bind보다 작고 후자의 두 매개변수는 동일합니다. 물론 또 다른 차이점이 있습니다. bindTo는 정적 메서드가 아닙니다. 하지만 클로저가 존재합니다. 🎜

🎜Example🎜

rrreee🎜위 함수의 출력은 bind🎜rrreee

의 출력과 유사합니다. 🎜트릭🎜 🎜🎜이 함수는 작곡가가 생성한 자동 로딩 소스 코드를 보다가 발견되었습니다. 이것은 작곡가에서 특별한 방식으로 사용됩니다. 다음은 작곡가의 코드 일부를 가로채는 것입니다🎜rrreee🎜. 위의 코드는 매우 이상합니다. call_user_func에서 첫인상은 잘못된 매개변수가 전달되었다는 것입니다. 실제로는 그렇지 않습니다. 이 함수는 <code>Closure 객체는 익명 함수이기도 합니다. 전달된 매개변수는 호출 가능 유형이기도 합니다. 반환된 클로저를 다시 보세요. use가 여기에 사용됩니다. 이는 클로저와 외부 변수를 연결하는 브리지입니다. 🎜여기서 일반 매개변수를 전달할 수 있는 이유는 PHP5에서는 객체 형식 매개변수와 실제 매개변수가 동일한 객체를 가리키고, 함수에서 객체를 수정하면 객체 외부에 반영되기 때문입니다. 🎜🎜그러니까 위와 같이 해도 괜찮고, 다른 방법도 있어요🎜rrreee🎜🎜요약🎜🎜🎜오랜 시간 블로그를 하지 않아서 가끔은 너무 짜증이 나서 진정이 안 되고, 가끔은 당신이 쓰고 싶은 것을 찾으세요. 그래도 침착해야 하고, 모든 일을 잘해야 하고, 무슨 일이 있어도 동요하지 말고 열린 마음을 갖고 모든 일을 침착하게 처리해야 합니다. 🎜

글을 쓰다 보니 갑자기 제가 고등학교 시절에 5.12 원촨 지진이 일어났던 때가 생각났습니다. 지진이 발생한 후에도 여전히 여진이 있었습니다. 여진이 나면 모두들 당황해서 몰려들었어요. 제 기억이 맞다면 저희는 5층에 있었어요. 예전에 그 선생님이 수업에 오셨는데, 그 선생님이 그 도시의 특별 선생님이셨어요. 맞아요) 우연히 여진이 닥쳐 모두가 또 정신이 혼미해질 뻔했어요. 이때 선생님께서 하신 말씀이 지금까지도 잊지 못할 것 같아요. 이렇게 작은 여진이면 사고가 날 확률이 높아집니다. 이 문장에는 약간의 부정적인 내용이 포함되어 있지만, 대부분은 차분한 마음, 상대적으로 큰 마음, 차분함과 결단력의 표현입니다. 배우고 싶다.

나타나야 할 것은 반드시 나타나고, 나타나지 말아야 할 것은 결코 나타나지 않습니다. 맹목적으로 높은 목표를 추구하고 너무 먼 목표를 추구하는 것은 쉽게 불안을 초래할 수 있습니다. 한마디로 말하면, 침착하십시오. 열린 마음을 가지고 득실에 대해 걱정하지 마세요. 命在骨子里,这种余震没必要这么慌挤下去,命硬的怎么都没事 열심히 일할수록 운이 좋아질 것입니다.

더 많은 프로그래밍 관련 지식을 보려면

프로그래밍 비디오
를 방문하세요! !

위 내용은 PHP Closure 클래스와 그 사용법에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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