首頁  >  文章  >  後端開發  >  PHP+Swoole的閉包寫法

PHP+Swoole的閉包寫法

angryTom
angryTom轉載
2019-10-15 09:26:102370瀏覽

JS程式設計師總是嘲笑PHP沒有閉包,今天就抽空寫一篇文章專門介紹PHP的閉包。從5.3版本開始PHP就增加了匿名函數支持,經過數個版本迭代到現在的PHP5.6、PHP7,PHP語言的閉包已經非常完善了。再結合Swoole提供的事件驅動支持,PHP的閉包功能非常強大而且很優雅。

匿名函數


        匿名函數是閉包的核心,匿名函數在PHP裡實際上是一個Closure類別的物件(請注意是物件) 。與普通的物件導向程式設計方式不同,匿名函數的程式碼是直接寫在呼叫處的,不需要額外寫一個類,編寫方法的程式碼。這樣的好處就是更直接。下面的範例是設定一個定時器,每2秒輸出hello world。

傳統寫法

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

閉包寫法

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

非閉包的傳統寫法,先聲明一個函數,再轉入函數名稱字串。兩段程式碼是分離的,不夠直覺。而閉包的寫法把定時器的聲明和定時器要執行的程式碼寫在了一起,邏輯非常清晰直觀。使用閉包語法可以很方便地編寫回呼函數。在事件驅動程式設計、排序、array_walk等需要使用者傳入一段執行程式碼的場景中,閉包的寫法非常優雅。

閉包更強大的地方在於它可以直接在呼叫處引入外部變數。 PHP中實作的方法就是use關鍵字。

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來呼叫當前物件的方法。在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中物件預設就是傳引用而非傳值。

 更多PHP相關知識,請造訪PHP中文網

以上是PHP+Swoole的閉包寫法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:rango.swoole.com。如有侵權,請聯絡admin@php.cn刪除