PHPコールバックのいくつかの書き方
PHPでは、無名関数の書き方が最も便利ですが、無名関数方式以外にもPHPには他のコールバックの書き方があります。以下はPHPのいくつかのコールバックの書き方の例です。
1、無名関数のコールバック
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';
$http_worker = new Worker("http://0.0.0.0:2345");
// 無名関数のコールバック
$http_worker->onMessage = function(TcpConnection $connection, Request $data)
{
// ブラウザにhello worldを送信
$connection->send('hello world');
};
Worker::runAll();
2、通常関数のコールバック
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';
$http_worker = new Worker("http://0.0.0.0:2345");
// 無名関数のコールバック
$http_worker->onMessage = 'on_message';
// 通常関数
function on_message(TcpConnection $connection, Request $request)
{
// ブラウザにhello worldを送信
$connection->send('hello world');
}
Worker::runAll();
3、コールバックとしてクラスのメソッドを使用する
MyClass.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
public function __construct(){}
public function onWorkerStart(Worker $worker){}
public function onConnect(TcpConnection $connection){}
public function onMessage(TcpConnection $connection, $message) {}
public function onClose(TcpConnection $connection){}
public function onWorkerStop(Worker $worker){}
}
起動スクリプト start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// MyClassを読み込む
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// オブジェクトを作成
$my_object = new MyClass();
// クラスのメソッドを呼び出す
$worker->onWorkerStart = array($my_object, 'onWorkerStart');
$worker->onConnect = array($my_object, 'onConnect');
$worker->onMessage = array($my_object, 'onMessage');
$worker->onClose = array($my_object, 'onClose');
$worker->onWorkerStop = array($my_object, 'onWorkerStop');
Worker::runAll();
注意:以上のコード構造では、リソース(MySQL接続、Redis接続、Memcache接続など)をコンストラクタで初期化することはできません。なぜなら$my_object = new MyClass();
はメインプロセスで実行されるからです。 MySQLを例に取ると、メインプロセスで初期化されたMySQL接続などのリソースは子プロセスに継承され、各子プロセスがこのデータベース接続を操作することができますが、サーバ側のMySQLサービスでは同じ接続になるため予期せぬエラーが発生する可能性があります。「mysql gone away」エラーなどです。
上記のコード構造でクラスのコンストラクタ内でリソースを初期化する場合、次のように書くことができます。
MyClass.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
protected $db = null;
public function __construct(){
// 仮にデータベース接続クラスがMyDbClassであるとします
$db = new MyDbClass();
}
public function onWorkerStart(Worker $worker){}
public function onConnect(TcpConnection $connection){}
public function onMessage(TcpConnection $connection, $message) {}
public function onClose(TcpConnection $connection){}
public function onWorkerStop(Worker $worker){}
}
起動スクリプト start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// クラスをonWorkerStartで初期化
$worker->onWorkerStart = function($worker) {
// MyClassを読み込む
require_once __DIR__.'/MyClass.php';
// オブジェクトを作成
$my_object = new MyClass();
// クラスのメソッドを呼び出す
$worker->onConnect = array($my_object, 'onConnect');
$worker->onMessage = array($my_object, 'onMessage');
$worker->onClose = array($my_object, 'onClose');
$worker->onWorkerStop = array($my_object, 'onWorkerStop');
};
Worker::runAll();
上記のコード構造では、onWorkerStartがサブプロセスにすでに属しているため、各サブプロセスが独自のMySQL接続を持っていて共有接続の問題が発生しません。
これにより、ビジネスコードのリロードもサポートされます。 MyClass.phpはサブプロセスにロードされるため、リロード規則に従ってMyClass.phpを変更し、直接リロードすることで変更を即座に反映させることができます。
4、クラスの静的メソッドをコールバックとして使用する
静的クラスMyClass.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
public static function onWorkerStart(Worker $worker){}
public static function onConnect(TcpConnection $connection){}
public static function onMessage(TcpConnection $connection, $message) {}
public static function onClose(TcpConnection $connection){}
public static function onWorkerStop(Worker $worker){}
}
起動スクリプト start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// MyClassを読み込む
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// クラスの静的メソッドを呼び出す。
$worker->onWorkerStart = array('MyClass', 'onWorkerStart');
$worker->onConnect = array('MyClass', 'onConnect');
$worker->onMessage = array('MyClass', 'onMessage');
$worker->onClose = array('MyClass', 'onClose');
$worker->onWorkerStop = array('MyClass', 'onWorkerStop');
// クラスに名前空間が含まれている場合は、次のように書きます
// $worker->onWorkerStart = array('your\namesapce\MyClass', 'onWorkerStart');
// $worker->onConnect = array('your\namesapce\MyClass', 'onConnect');
// $worker->onMessage = array('your\namesapce\MyClass', 'onMessage');
// $worker->onClose = array('your\namesapce\MyClass', 'onClose');
// $worker->onWorkerStop = array('your\namesapce\MyClass', 'onWorkerStop');
Worker::runAll();
注意:PHPの動作原則に従い、newがないとコンストラクタは呼び出されません。また、静的クラスのメソッドでは$this
を使用することはできません。