PHP Çeşitli Geri Çağırma Yazım Şekilleri

PHP'de anonim fonksiyon kullanarak geri çağırma yazmak en pratik olanıdır, ancak anonim fonksiyon dışında PHP'de başka geri çağırma yazım şekilleri de bulunmaktadır. Aşağıda PHP'nin çeşitli geri çağırma yazım şekillerine örnekler verilmiştir.

1. Anonim Fonksiyon Geri Çağrısı

<?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");

// Anonim fonksiyon geri çağrısı
$http_worker->onMessage = function(TcpConnection $connection, Request $data)
{
    // Tarayıcıya hello world gönder
    $connection->send('hello world');
};

Worker::runAll();

2. Normal Fonksiyon Geri Çağrısı

<?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");

// Normal fonksiyon geri çağrısı
$http_worker->onMessage = 'on_message';

// Normal fonksiyon
function on_message(TcpConnection $connection, Request $request)
{
    // Tarayıcıya hello world gönder
    $connection->send('hello world');
}

Worker::runAll();

3. Sınıf Metodu Olarak Geri Çağrı

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){}
}

Başlatma Scripti start.php

<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

// MyClass'ı yükle
require_once __DIR__.'/MyClass.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// Bir nesne oluştur
$my_object = new MyClass();

// Sınıfın metodlarını çağır
$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();

Dikkat:
Yukarıdaki kod yapısında kaynakları (MySQL bağlantısı, Redis bağlantısı, Memcache bağlantısı vb.) yapıcı fonksiyonda başlatmak yasaktır, çünkü $my_object = new MyClass(); ana süreçte çalışır. MySQL örneğinde, ana süreçte başlatılan MySQL bağlantıları gibi kaynaklar alt süreçler tarafından miras alınır, her bir alt süreç bu veritabanı bağlantısını kullanabilir, ancak bu bağlantılar MySQL sunucusunda aynı bağlantıya karşılık geleceği için beklenmedik hatalar meydana gelebilir, örneğin mysql gone away hatası.

Yukarıdaki kod yapısında sınıfın yapıcı fonksiyonunda kaynakları başlatmak gerekiyorsa, aşağıdaki yazım şekli kullanılabilir.
MyClass.php

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
class MyClass{
    protected $db = null;
    public function __construct(){
        // Veritabanı bağlantı sınıfının MyDbClass olduğunu varsayıyoruz
        $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){}
}

Başlatma Scripti start.php

<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// onWorkerStart içinde sınıfı başlat
$worker->onWorkerStart = function($worker) {
    // MyClass'ı yükle
    require_once __DIR__.'/MyClass.php';

    // Bir nesne oluştur
    $my_object = new MyClass();

    // Sınıfın metodlarını çağır
    $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();

Yukarıdaki kod yapısında onWorkerStart çalıştığında zaten alt süreçin bir parçasıdır, bu nedenle her bir alt süreç kendi MySQL bağlantısını kurar, bu yüzden paylaşılan bağlantı sorunları olmaz. Ayrıca bu yöntemin bir avantajı, iş kodunun yeniden yüklenmesini desteklemesidir. MyClass.php alt süreçte yüklendiğinden, yeniden yükleme kurallarına göre iş değiştirdiğinizde MyClass.php'yi doğrudan yeniden yükleyerek etkili olur.

4. Sınıfın Statik Metodu Olarak Geri Çağrı

Statik Sınıf 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){}
}

Başlatma Scripti start.php

<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

// MyClass'ı yükle
require_once __DIR__.'/MyClass.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// Sınıfın statik metodlarını çağır.
$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');

// Eğer sınıf bir isim alanına sahipse, benzer bir yazım şekli kullanılır
// $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();

Dikkat: PHP'nin çalışma mekanizması gereği, eğer new çağrısı yapılmazsa, yapıcı fonksiyon çağrılmayacaktır, ayrıca statik sınıf metodları içinde $this kullanılamaz.