PHP Callback Methods
Using anonymous functions for callbacks in PHP is the most convenient, but besides anonymous functions, PHP has other ways to write callbacks. Here are examples of different callback methods in PHP.
1. Anonymous Function Callbacks
<?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");
// Anonymous function callback
$http_worker->onMessage = function(TcpConnection $connection, Request $data)
{
// Send hello world to the browser
$connection->send('hello world');
};
Worker::runAll();
2. Regular Function Callbacks
<?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");
// Anonymous function callback
$http_worker->onMessage = 'on_message';
// Regular function
function on_message(TcpConnection $connection, Request $request)
{
// Send hello world to the browser
$connection->send('hello world');
}
Worker::runAll();
3. Class Methods as Callbacks
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 Script start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// Load MyClass
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Create an object
$my_object = new MyClass();
// Call class methods
$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();
Note:
In the above code structure, it is not allowed to initialize resources (MySQL connections, Redis connections, Memcache connections, etc.) in the constructor, because $my_object = new MyClass(); runs in the main process. For MySQL, resources such as MySQL connections initialized in the main process will be inherited by child processes, each child process can operate this database connection, but these connections correspond to the same connection on the MySQL server, which can lead to unpredictable errors, such as mysql gone away errors.
If resources need to be initialized in the class constructor within the above code structure, the following method can be used.
MyClass.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
protected $db = null;
public function __construct(){
// Assume the database connection class is 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 Script start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Initialize class in onWorkerStart
$worker->onWorkerStart = function($worker) {
// Load MyClass
require_once __DIR__.'/MyClass.php';
// Create an object
$my_object = new MyClass();
// Call class methods
$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();
In the above code structure, the onWorkerStart runs in the child process, meaning each child process establishes its own MySQL connection, so there will be no issue of shared connections. This also has the benefit of supporting business code reload. Since MyClass.php is loaded in the child process, any changes made to MyClass.php according to the reload rules will take effect directly after the reload.
4. Static Class Methods as Callbacks
Static Class 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 Script start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// Load MyClass
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Call the static methods of the class.
$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');
// If the class has a namespace, it would look like this
// $worker->onWorkerStart = array('your\namespace\MyClass', 'onWorkerStart');
// $worker->onConnect = array('your\namespace\MyClass', 'onConnect');
// $worker->onMessage = array('your\namespace\MyClass', 'onMessage');
// $worker->onClose = array('your\namespace\MyClass', 'onClose');
// $worker->onWorkerStop = array('your\namespace\MyClass', 'onWorkerStop');
Worker::runAll();
Note: According to PHP's execution mechanism, if new is not called, the constructor will not be invoked, and static class methods are not allowed to use $this.