日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
解析PHP閉包及Clourse類方法的作用

0x00 前言

創(chuàng)新互聯(lián)建站自2013年起,先為中原等服務(wù)建站,中原等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為中原企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

閉包是指在創(chuàng)建時(shí)封裝周圍狀態(tài)的函數(shù)。即使閉包所在的環(huán)境不存在了,閉包中封裝的狀態(tài)依然存在。

在 php 里所有的閉包都是 Clourse 類所實(shí)例化的一個(gè)對象,也就是說閉包與其他 PHP 對象沒有什么不同。而一個(gè)對象就必然有其方法和屬性,這篇文章將總結(jié) PHP 中閉包的基礎(chǔ)用法和 Clourse 類方法的作用。【推薦:PHP視頻教程】

0x01 閉包基本用法

下面看看最基本的閉包使用方法:


嘿,這段代碼最直觀的感受就是將一個(gè)函數(shù)賦值給了 $hello 變量,然后通過 $hello 直接調(diào)用它。但是這個(gè)閉包并沒有從父作用域中繼承變量(就是封裝周圍狀態(tài)),我們可以通過 use 關(guān)鍵字從閉包的父作用域繼承變量。示例如下:


PHP 7.1 起,use 不能傳入此類變量: superglobals、 $this 或者和參數(shù)重名。

此外在使用 use 關(guān)鍵字時(shí),父作用域的變量是通過值傳遞進(jìn)閉包的。也就是說一旦閉包創(chuàng)建完成,外部的變量即使修改也不會影響傳遞進(jìn)閉包內(nèi)的值(就是即使閉包所在的環(huán)境不存在了,閉包中封裝的狀態(tài)依然存在)。示例如下:


傳遞變量的引用可以使閉包修改外部變量的值,示例如下:


注意:PHP 中傳遞對象時(shí),默認(rèn)是以引用傳遞所以在閉包內(nèi)操作 use 傳遞的對象時(shí)需要特別注意。示例如下:

name = 'Lai Fu';
};
$changeName();
echo $dog->name;
// 輸出 Lai Fu

0x02 Clourse 類

證明閉包只是 Clourse 類對象


上面的代碼將輸出 Closure 證明了閉包只是一個(gè)普通的 Closure 類對象。

Clourse 類摘要

我們可以從 PHP 官方手冊 看到閉包類的相關(guān)信息,下面是我在 PhpStorm 的本地文檔查看到 Clourse 類摘要。

/**
 * Class used to represent anonymous functions.
 * 

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. *

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 '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. * @return Closure Returns the newly created Closure object or FALSE on failure */ function bindTo($newthis, $newscope = 'static') { } /** * 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 '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. * @return Closure Returns the newly created Closure object or FALSE on failure */ static function bind(Closure $closure, $newthis, $newscope = 'static') { } /** * 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) {} }

首先 Clourse 類為 final 類,也就是說它將無法被繼承,其次它的構(gòu)造函數(shù) __construct 被設(shè)為 private 即無法通過 new 關(guān)鍵字實(shí)例化閉包對象,這兩點(diǎn)保證了閉包只能通過 function (...) use(...) {...} 這種語法實(shí)例化 。

為什么閉包可以當(dāng)作函數(shù)執(zhí)行?

從上面的類摘要中我們看出 Clourse 類實(shí)現(xiàn)了 __invoke 方法,在 PHP 官方手冊中對該方法解釋如下:

當(dāng)嘗試以調(diào)用函數(shù)的方式調(diào)用一個(gè)對象時(shí),__invoke() 方法會被自動調(diào)用。

這就是閉包可以被當(dāng)作函數(shù)執(zhí)行的原因。

綁定指定的$this對象和類作用域

在允許使用閉包路由的框架中(如:Slim),我們可以看見如下寫法:

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

在一個(gè)閉包居然能中使用 $this?這個(gè) $this 指向哪個(gè)對象?

通過 bindTo 和 bind 方法都能夠?qū)崿F(xiàn)綁定 $this 和類作用域的功能,示例如下:

num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas);
$newAdd1();
// 輸出 2
$newAdd2 = Closure::bind($add, $pandas);
$newAdd2();
// 輸出 3

上面的這段例子將指定對象綁定為閉包的 $this,但是我們并沒有指定類作用域。所以如果將 Pandas 類的 $num 屬性改寫為 protected 或 private 則會拋出一個(gè)致命錯誤!

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

在需要訪問綁定對象的非公開屬性或方法時(shí),我們需要指定類作用域,示例如下:

num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas, $pandas);
$newAdd1();
// 輸出 2
$newAdd2 = Closure::bind($add, $pandas, 'Pandas');
$newAdd2();
// 輸出 3

這里我們看見 bindTo 和 bind 方法都指定了 $newscope 參數(shù),$newscope 參數(shù)默認(rèn)為 static 即不改變類作用域。$newscope 參數(shù)接受類名或?qū)ο?,并將閉包的類作用域改為指定的類作用域,此時(shí) Pandas 類的 $num 屬性便能夠被閉包訪問。

一次性綁定 $this 對象和類作用域并執(zhí)行(PHP7)

bindTo 和 bind 方法每次指定新的對象和類作用域時(shí)都要將原閉包進(jìn)行復(fù)制然后返回新的閉包,在需要多次修改綁定對象的情景下便顯得繁瑣,所以 PHP7 提供了一個(gè)新的方法 call 它能將閉包臨時(shí)的綁定到一個(gè)對象中(類作用域同時(shí)被修改為該對象所屬的類)并執(zhí)行。示例如下:

num += $num;
    echo $this->num . PHP_EOL;
};
$add->call($pandas, 5);
// 輸出 6

Callable 轉(zhuǎn)為閉包(PHP7.1)

在 PHP7.1 中 Closure 類存在 fromCallable 方法能夠?qū)?callable 類型的值轉(zhuǎn)為閉包,示例如下:


這種寫法還是挺爽的畢竟通過閉包調(diào)用總比用 call_user_func 函數(shù)調(diào)用爽的多^_^。

0x03 總結(jié)


網(wǎng)頁標(biāo)題:解析PHP閉包及Clourse類方法的作用
轉(zhuǎn)載來源:http://www.dlmjj.cn/article/coojoog.html