blog

Swooleのクロージャの書き方、とてもいい。

今日はPHPのクロージャに特化した記事を書きます。バージョン5.3以降、PHPは無名関数をサポートするようになり、その後PHP5.6、PHP7と改良を重ね、PHP言語のクロージャは非常に完璧になりまし...

Dec 25, 2020 · 4 min. read
シェア

今日はPHPのクロージャに特化した記事を書きます。PHPのバージョン5.3から無名関数のサポートが追加され、現在のPHP5.6とPHP7まで何度か繰り返された後、PHP言語のクロージャは非常によく開発されました。Swoole が提供するイベント駆動型のサポートと組み合わせることで、 PHP のクロージャは非常に強力かつエレガントになります。

匿名関数

匿名関数はクロージャの核心です。 匿名関数は、実際には PHP のクロージャクラスのオブジェクトです。通常のオブジェクト指向プログラミングスタイルとは異なり、 匿名関数のコードは呼び出し時に直接記述されます。これは、よりわかりやすいという利点があります。次の例では、2 秒ごとに hello world を出力するタイマーを設定します。

伝統的な書き方

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

クロージャ

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

従来の非閉鎖型パッケージの書き方では、まず関数を宣言し、次に関数名の文字列を転送します。この2つのコードは分離しており、直感的ではありません。クロージャの書き方では、タイマーの宣言とタイマーが実行しなければならないコードが一緒になっており、ロジックが非常に明確で直感的です。クロージャ構文を使うと、コールバック関数を簡単に書くことができます。イベントドリブンプログラミング、ソート、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;
});

クロージャの書き方では、globalグローバル変数を使わずに、useを使って直接現在の$str変数を導入します。また、swooleのイベントドリブンプログラミングモデルの場合、グローバル変数が1つしかないため、globalを使用して非同期並行処理を実現することはできません。 同時に複数のクライアントリクエストがあり、各リクエストが異なる内容を出力するためにデータベースに照会を行う必要がある場合、従来のプログラミング方法を実現するのは容易ではなく、グローバル変数の配列を使用して、クライアントのIDをそれぞれのデータへのKEYとして保存する必要があります。の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以降では、無名関数を使用せずに導入されています。

this、これは匿名関数で直接使用できます。

thisは、カレントオブジェクトのメソッドを呼び出すために、無名関数の中で直接使用することができます。swooleプログラミングでは、この機能を使用して、パスに導入された$servオブジェクトの使用を減らすことができます。

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

さらに、クロージャ内の外部変数を変更したい場合は、使用する変数に & 参照記号を追加します。PHP のデフォルトでは、オブジェクトは値ではなく参照で渡されるからです。

より多くの学習コンテンツは、訪問することができます!

Read next

CVPR2018 Relation Net解析の全容をフライング・パドルで再現する

フライング・パドルの開発者は、東京航空大学大学院修士課程修了、マシンビジョン・アルゴリズム・エンジニアのXingyu Tongと言います。\n\nRelation NetはCVPR2018の論文です:\n\n\nこの論文の著者らは、視覚認識タスクにおいて、モデルの学習には大量のラベル付けされた

Dec 25, 2020 · 10 min read