Différentes écritures de rappel en PHP
L'écriture de rappels avec des fonctions anonymes est la méthode la plus pratique en PHP, mais en plus de cette méthode, il existe d'autres façons de mettre en œuvre des rappels. Voici plusieurs exemples de rappel en PHP.
1. Rappel avec des fonctions anonymes
<?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");
// Rappel avec fonction anonyme
$http_worker->onMessage = function(TcpConnection $connection, Request $data)
{
// Envoyer hello world au navigateur
$connection->send('hello world');
};
Worker::runAll();
2. Rappel avec des fonctions normales
<?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");
// Rappel avec fonction anonyme
$http_worker->onMessage = 'on_message';
// Fonction normale
function on_message(TcpConnection $connection, Request $request)
{
// Envoyer hello world au navigateur
$connection->send('hello world');
}
Worker::runAll();
3. Méthode de classe en tant que rappel
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){}
}
Script de démarrage start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// Charger MyClass
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Créer un objet
$my_object = new MyClass();
// Appeler les méthodes de la classe
$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();
Remarque :
La structure de code ci-dessus ne permet pas d'initialiser des ressources (connexion MySQL, connexion Redis, connexion Memcache, etc.) dans le constructeur, car $my_object = new MyClass(); s'exécute dans le processus principal. À titre d'exemple avec MySQL, les ressources comme la connexion MySQL initialisées dans le processus principal seront héritées par les sous-processus, chaque sous-processus pourra manipuler cette connexion de base de données, mais ces connexions correspondent à la même connexion côté serveur MySQL, ce qui peut entraîner des erreurs imprévues, telles que l'erreur mysql gone away.
Si la structure de code ci-dessus nécessite d'initialiser des ressources dans le constructeur de la classe, vous pouvez utiliser l'écriture suivante.
MyClass.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
protected $db = null;
public function __construct(){
// Supposons que la classe de connexion à la base de données soit 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){}
}
Script de démarrage start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Initialiser la classe dans onWorkerStart
$worker->onWorkerStart = function($worker) {
// Charger MyClass
require_once __DIR__.'/MyClass.php';
// Créer un objet
$my_object = new MyClass();
// Appeler les méthodes de la classe
$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();
Dans la structure de code ci-dessus, onWorkerStart s'exécute déjà dans le contexte de sous-processus, chaque sous-processus établissant sa propre connexion MySQL, donc il n'y aura pas de problème de connexion partagée.
Un autre avantage est que cela prend en charge le rechargement du code métier. Étant donné que MyClass.php est chargé dans le sous-processus, il suffit de recharger après avoir modifié MyClass.php pour que les changements prennent effet.
4. Méthode statique de classe en tant que rappel
Classe statique 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){}
}
Script de démarrage start.php
<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
// Charger MyClass
require_once __DIR__.'/MyClass.php';
$worker = new Worker("websocket://0.0.0.0:2346");
// Appeler les méthodes statiques de la classe.
$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');
// Si la classe a un namespace, cela ressemble à ceci
// $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();
Remarque : Selon le mécanisme d'exécution de PHP, si vous n'utilisez pas new, le constructeur ne sera pas appelé. De plus, il n'est pas permis d'utiliser $this dans les méthodes de classe statiques.