Swoole的閉包寫法,很nice

今天寫一篇文章來專門介紹一下PHP的閉包。從5.3版本開始PHP就增長了匿名函數支持,通過數個版本迭代到如今的PHP5.六、PHP7,PHP語言的閉包已經很是完善了。再結合Swoole提供的事件驅動支持,PHP的閉包功能很是強大並且很優雅。html

匿名函數

匿名函數是閉包的核心,匿名函數在PHP裏其實是一個Closure類的對象(請注意是對象)。與普通的面向對象編程方式不一樣,匿名函數的代碼是直接寫在調用處的,不須要額外寫一個類,編寫方法的代碼。這樣的好處就是更直接。下面的示例是設置一個定時器,每2秒輸出hello world。react

傳統寫法

function timer () {
    echo "hello world";
}
Swoole\Timer::tick(2000, 'timer');

閉包寫法

Swoole\Timer::tick(2000, function () {
    echo "hello world";
});

非閉包的傳統寫法,先要聲明一個函數,再轉入函數名稱字符串。兩段代碼是分離的,不夠直觀。而閉包的寫法把定時器的聲明和定時器要執行的代碼寫在了一塊兒,邏輯很是清晰直觀。使用閉包語法能夠很方便編寫回調函數。在事件驅動編程、排序、array_walk等須要用戶傳入一段執行代碼的場景中,閉包的寫法很是優雅。面試

閉包更強大的地方在於它能夠直接在調用處引入外部變量。PHP中實現的方法就是use關鍵詞。sql

Use語法

若是剛纔的定時器須要傳入一個變量,傳統的寫法只能經過全局變量來實現。與JS不一樣,PHP的變量引入是顯式的,若是要引用外部變量必須使用use來聲明。而JS是隱式的,匿名函數內部能夠隨意操做外部變量,無需聲明。這樣好處是少寫了一點代碼,缺點是存在風險和混亂。數據庫

傳統寫法

$str = "hello world";
function timer () {
    global $str;
    echo $str;
}
Swoole\Timer::tick(2000, 'timer');

閉包寫法

$str = "hello world";
Swoole\Timer::tick(2000, function () use ($str) {
    echo $str;
});

閉包寫法使用use直接引入了當前的$str變量,而不須要使用global全局變量。另外若是是在swoole的事件驅動編程模式,使用global就沒法實現異步併發了,由於global全局變量只有1個,若是同時有多個客戶端請求,每一個請求要查詢數據庫,輸出不一樣的內容,傳統的編程方法就不太容易實現,須要使用全局變量數組,以客戶端的ID爲KEY保存各自的數據。編程

傳統寫法

$requestArray = array();
$dbResultArray = array();

function my_request($request, $response) {
    global $dbResultArray, $requestArray;
    $queryId = $db->query($sql, 'get_result');
    $requestArray[$request->fd] = array($request, $response);
    $dbResultArray[$queryId] = $request->fd;
}

function get_result($queryId, $queryResult) {
    global $dbResultArray, $requestArray;
    list($request, $response) = $requestArray[$dbResultArray[$queryId]];
    $response->end($queryResult);
}

$server->on('request', 'my_request');

 

閉包寫法

$server->on('request', function ($request, $response) {
    $queryId = $db->query($sql, function ($queryId, $queryResult) use ($request, $response) {
        $response->end($queryResult);
    });
});

傳統的寫法很是複雜,須要反覆屢次從全局數組保存/提取數據。而閉包的寫法很是簡潔優雅,只用了幾行代碼就實現了一樣的功能。閉包寫法很是適合用來編寫異步非阻塞回調模式的服務器程序。目前熱門的編程語言中只有PHP和JS具有這種能力。數組

閉包更多特性

在類的方法中使用匿名函數,5.4以上的版本無需使用use引入this,直接能夠在匿名函數中使用this使用this來調用當前對象的方法。在swoole編程中,能夠利用此特性減小$serv對象的use引入傳遞。服務器

class Server extends Swoole\Server {
    function onReceive($serv, $fd, $reactorId, $data) {
        $db->query($sql, function ($queryId, $queryResult) use ($fd) {
            $this->send($fd, $queryResult);
        }
    }
}

另外若是但願在閉包函數中修改外部變量,能夠在use時爲變量增長&引用符號便可。注意對象類型不須要加&,由於在PHP中對象默認就是傳引用而非傳值。swoole


 

相關文章
相關標籤/搜索