成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 閉包那些事兒

winterdawn / 413人閱讀

摘要:注理論上講閉包和匿名函數(shù)是不同的概念,不過(guò)將其視作相同的概念。匿名函數(shù)可以從父作用域繼承變量,而這個(gè)父作用域是定義該閉包的函數(shù)不一定是調(diào)用它的函數(shù)。

匿名函數(shù)

匿名函數(shù),也叫閉包函數(shù),說(shuō)白了就是“沒(méi)有名字的函數(shù)”,和一般函數(shù)結(jié)構(gòu)一樣,只是少了函數(shù)名以及最后需要加上分號(hào);

注:理論上講閉包和匿名函數(shù)是不同的概念,不過(guò)PHP將其視作相同的概念。
$func = function()
{
    echo "Hello World" . PHP_EOL;
};
$func();

匿名函數(shù)和普通函數(shù)的區(qū)分有:

匿名函數(shù)也可以作為變量的值來(lái)使用。

匿名函數(shù)可以從父作用域繼承變量,而這個(gè)父作用域是定義該閉包的函數(shù)(不一定是調(diào)用它的函數(shù))。

$message = "hello";
$example = function () use ($message) {
    return $message;
};
$message = "world";
echo $example();

輸出:hello

注意:必須使用use關(guān)鍵字將變量傳遞進(jìn)去才行,具體見(jiàn)官方文檔。

閉包類

定義一個(gè)閉包函數(shù),其實(shí)就是實(shí)例化一個(gè)閉包類(Closure)對(duì)象:

$func = function()
{
    echo "hello world" . PHP_EOL;
};
var_dump($func);

輸出:
object(Closure)#1 (0) {
}

類摘要:

Closure {
     __construct ( void )
     public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] )
     public Closure bindTo ( object $newthis [, mixed $newscope = "static" ] )
}

除了以上方法,閉包還實(shí)現(xiàn)了一個(gè)__invoke()魔術(shù)方法,當(dāng)嘗試以調(diào)用函數(shù)的方式調(diào)用一個(gè)對(duì)象時(shí),__invoke() 方法會(huì)被自動(dòng)調(diào)用。

bindTo 方法

接下來(lái)我們來(lái)看看bindTo方法,通過(guò)該方法,我們可以把閉包的內(nèi)部狀態(tài)綁定到其他對(duì)象上。這里bindTo方法的第二個(gè)參數(shù)顯得尤為重要,其作用是指定綁定閉包的那個(gè)對(duì)象所屬的PHP類,這樣,閉包就可以在其他地方訪問(wèn)綁定閉包的對(duì)象中受保護(hù)和私有的成員變量。

你會(huì)發(fā)現(xiàn),PHP框架經(jīng)常使用bindTo方法把路由URL映射到匿名回調(diào)函數(shù)上,框架會(huì)把匿名回調(diào)函數(shù)綁定到應(yīng)用對(duì)象上,這樣在匿名函數(shù)中就可以使用$this關(guān)鍵字引用重要的應(yīng)用對(duì)象:

class App {
    protected $routes = [];
    protected $responseStatus = "200 OK";
    protected $responseContentType = "text/html";
    protected $responseBody = "Hello World";

    public function addRoute($path, $callback) {
        $this->routes[$path] = $callback->bindTo($this, __CLASS__);
    }

    public function dispatch($path) {
        foreach ($this->routes as $routePath => $callback) {
            if( $routePath === $path) {
                $callback();
            }
        }
        header("HTTP/1.1 " . $this->responseStatus);
        header("Content-Type: " . $this->responseContentType);
        header("Content-Length: " . mb_strlen($this->responseBody));
        echo $this->responseBody;
    }

}

這里我們需要重點(diǎn)關(guān)注addRoute方法,這個(gè)方法的參數(shù)分別是一個(gè)路由路徑和一個(gè)路由回調(diào),dispatch方法的參數(shù)是當(dāng)前HTTP請(qǐng)求的路徑,它會(huì)調(diào)用匹配的路由回調(diào)。第9行是重點(diǎn)所在,我們將路由回調(diào)綁定到了當(dāng)前的App實(shí)例上。這么做能夠在回調(diào)函數(shù)中處理App實(shí)例的狀態(tài):

$app = new App();
$app->addRoute(‘/user’, function(){
    $this->responseContentType = ‘a(chǎn)pplication/json;charset=utf8’;
    $this->responseBody = "世界你好";
});
$app->dispatch("/user");
IoC 容器

匿名函數(shù)可以從父作用域繼承變量,而這個(gè)父作用域是定義該閉包的函數(shù)(不一定是調(diào)用它的函數(shù))。

利用這個(gè)特性,我們可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的控制反轉(zhuǎn)IoC容器:

class Container
{
    protected static $bindings;
 
    public static function bind($abstract, Closure $concrete)
    {
        static::$bindings[$abstract] = $concrete;
    }
 
    public static function make($abstract)
    {
        return call_user_func(static::$bindings[$abstract]);
    }
}
 
class talk
{
    public function greet($target)
    {
        echo "Hello " . $target->getName();
    }
}

class A
{
    public function getName()
    {
        return "World";
    }
}
 
// 創(chuàng)建一個(gè)talk類的實(shí)例
$talk = new talk();
 
// 將A類綁定至容器,命名為foo
Container::bind("foo", function() {
    return new A;
});
 
// 通過(guò)容器取出實(shí)例
$talk->greet(Container::make("foo")); // Hello World

上述例子中,只有在通過(guò)make方法獲取實(shí)例的時(shí)候,實(shí)例才被創(chuàng)建,這樣使得我們可以實(shí)現(xiàn)容器。

Laravel框架底層也大量使用了閉包以及bindTo方法,利用好閉包可以實(shí)現(xiàn)更多的高級(jí)特性如事件觸發(fā)等。


以上為閉包學(xué)習(xí)筆記,部分參考了網(wǎng)上的一些文章。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28403.html

相關(guān)文章

  • 2019前端面試那些事兒

    摘要:雖然今年沒(méi)有換工作的打算但為了跟上時(shí)代的腳步還是忍不住整理了一份最新前端知識(shí)點(diǎn)知識(shí)點(diǎn)匯總新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式和的區(qū)別使用的好處標(biāo)簽廢棄的標(biāo)簽,和一些定位寫(xiě)法放置位置和原因什么是漸進(jìn)式渲染模板語(yǔ)言原理盒模型,新特性,偽 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總1.HTMLHTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪...

    JeOam 評(píng)論0 收藏0
  • 2019前端面試那些事兒

    摘要:雖然今年沒(méi)有換工作的打算但為了跟上時(shí)代的腳步還是忍不住整理了一份最新前端知識(shí)點(diǎn)知識(shí)點(diǎn)匯總新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式和的區(qū)別使用的好處標(biāo)簽廢棄的標(biāo)簽,和一些定位寫(xiě)法放置位置和原因什么是漸進(jìn)式渲染模板語(yǔ)言原理盒模型,新特性,偽 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總1.HTMLHTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪...

    QLQ 評(píng)論0 收藏0
  • PHP那些事兒

    摘要:封禁策略為一個(gè)自然分鐘內(nèi)請(qǐng)求簽到接口次則封禁該分鐘,如何操作設(shè)置兩個(gè)來(lái)支撐此問(wèn)題獲取封禁獲取次數(shù)只提供內(nèi)存,現(xiàn)在要做一個(gè)活動(dòng),參與活動(dòng)的用戶為,請(qǐng)問(wèn)如何設(shè)計(jì)可考慮用的和命令來(lái)實(shí)現(xiàn)此需求,對(duì)其進(jìn)行占位,并且各的占位才占有的空間,所有空間 1、封禁策略為一個(gè)自然分鐘內(nèi)請(qǐng)求簽到接口500次則封禁該IP10分鐘,如何操作? 2、只提供10M內(nèi)存,現(xiàn)在要做一個(gè)活動(dòng),參與活動(dòng)的用戶userId為...

    X_AirDu 評(píng)論0 收藏0
  • 【nginx】nginx 配置那些事兒

    摘要:是一款具有高負(fù)載能力的服務(wù)器,也是架構(gòu)的主要角色之一。多站點(diǎn)設(shè)置前面我們修改配置文件的代碼位置,都是在下的里。如果想項(xiàng)目和項(xiàng)目均適用端口,則需要利用做反向代理設(shè)置。 nginx 是一款具有高負(fù)載能力的 web 服務(wù)器,也是 LNMP 架構(gòu)的主要角色之一?,F(xiàn)在越來(lái)越多的開(kāi)發(fā)者選擇 nginx 作為 php 的好搭檔,替代 apache 的位置。下面我以 Mac 系統(tǒng)為例,介紹下 ngin...

    lunaticf 評(píng)論0 收藏0
  • 【nginx】nginx 配置那些事兒

    摘要:是一款具有高負(fù)載能力的服務(wù)器,也是架構(gòu)的主要角色之一。多站點(diǎn)設(shè)置前面我們修改配置文件的代碼位置,都是在下的里。如果想項(xiàng)目和項(xiàng)目均適用端口,則需要利用做反向代理設(shè)置。 nginx 是一款具有高負(fù)載能力的 web 服務(wù)器,也是 LNMP 架構(gòu)的主要角色之一?,F(xiàn)在越來(lái)越多的開(kāi)發(fā)者選擇 nginx 作為 php 的好搭檔,替代 apache 的位置。下面我以 Mac 系統(tǒng)為例,介紹下 ngin...

    PrototypeZ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<