add

int \Workerman\Timer::add(float $time_interval, callable $callback [,$args = array(), bool $persistent = true])

特定の関数またはクラスメソッドを定期的に実行します。

注意:タイマーは現在のプロセス内で実行され、workermanではタイマーを実行するために新しいプロセスやスレッドは作成されません。

パラメータ

time_interval

何秒ごとに実行するか、単位は秒で、小数点もサポート。0.001までの精度、つまりミリ秒単位で指定できます。

callback

コールバック関数注意:コールバック関数がクラスメソッドである場合、そのメソッドはpublic属性でなければなりません

args

コールバック関数の引数で、必ず配列でなければならず、配列要素は引数の値です。

persistent

持続的かどうか、一度だけ定期実行したい場合は、falseを渡します(1回だけ実行されるタスクは実行後自動的に破棄され、Timer::del()を呼び出す必要はありません)。デフォルトはtrueで、常に定期実行されます。

戻り値

整数を返し、タイマーのtimeridを表します。これを使用してTimer::del($timerid)を呼び出すことで、このタイマーを破棄できます。

1、定期関数を無名関数(クロージャ)にする

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

$task = new Worker();
// タイムタスクを実行するプロセス数を設定、ビジネスに並行問題があるか注意
$task->count = 1;
$task->onWorkerStart = function(Worker $task)
{
    // 2.5秒ごとに実行
    $time_interval = 2.5;
    Timer::add($time_interval, function()
    {
        echo "task run\n";
    });
};

// workerを実行
Worker::runAll();

2、特定のプロセスのみでタイマーを設定

1つのworkerインスタンスに4つのプロセスがあり、id番号が0のプロセスだけにタイマーを設定します。

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

$worker = new Worker();
$worker->count = 4;
$worker->onWorkerStart = function(Worker $worker)
{
    // id番号が0のプロセスのみタイマーを設定し、他の1、2、3のプロセスには設定しない
    if($worker->id === 0)
    {
        Timer::add(1, function(){
            echo "4つのworkerプロセスで、0番プロセスのみタイマーを設定\n";
        });
    }
};
// workerを実行
Worker::runAll();

3、定期関数を無名関数で、クロージャを使用して引数を渡す

use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->count = 8;
// 接続確立時に対応する接続にタイマーを設定
$ws_worker->onConnect = function(TcpConnection $connection)
{
    // 10秒ごとに実行
    $time_interval = 10;
    $connect_time = time();
    // connectionオブジェクトに一時的にtimer_id属性を追加してタイマーidを保存
    $connection->timer_id = Timer::add($time_interval, function()use($connection, $connect_time)
    {
         $connection->send($connect_time);
    });
};
// 接続が閉じられたとき、対応する接続のタイマーを削除
$ws_worker->onClose = function(TcpConnection $connection)
{
    // タイマーを削除
    Timer::del($connection->timer_id);
};

// workerを実行
Worker::runAll();

4、定期関数を無名関数で、タイマーインターフェースを使って引数を渡す

use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->count = 8;
// 接続確立時に対応する接続にタイマーを設定
$ws_worker->onConnect = function(TcpConnection $connection)
{
    // 10秒ごとに実行
    $time_interval = 10;
    $connect_time = time();
    // connectionオブジェクトに一時的にtimer_id属性を追加してタイマーidを保存
    $connection->timer_id = Timer::add($time_interval, function($connection, $connect_time)
    {
         $connection->send($connect_time);
    }, array($connection, $connect_time));
};
// 接続が閉じられたとき、対応する接続のタイマーを削除
$ws_worker->onClose = function(TcpConnection $connection)
{
    // タイマーを削除
    Timer::del($connection->timer_id);
};

// workerを実行
Worker::runAll();

5、定期関数を普通の関数にする

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

// 普通の関数
function send_mail($to, $content)
{
    echo "メールを送信中 ...\n";
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    $to = 'workerman@workerman.net';
    $content = 'こんにちは workerman';
    // 10秒後にメール送信タスクを実行、最後の引数にfalseを渡し、1回のみ実行
    Timer::add(10, 'send_mail', array($to, $content), false);
};

// workerを実行
Worker::runAll();

6、定期関数をクラスのメソッドにする

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

class Mail
{
    // 注意、コールバック関数はpublicでなければなりません
    public function send($to, $content)
    {
        echo "メールを送信中 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function($task)
{
    // 10秒後にメールを1回送信
    $mail = new Mail();
    $to = 'workerman@workerman.net';
    $content = 'こんにちは workerman';
    Timer::add(10, array($mail, 'send'), array($to, $content), false);
};

// workerを実行
Worker::runAll();

7、定期関数をクラスのメソッド(クラス内部でタイマーを使用)

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

class Mail
{
    // 注意、コールバック関数はpublicでなければなりません
    public function send($to, $content)
    {
        echo "メールを送信中 ...\n";
    }

    public function sendLater($to, $content)
    {
        // コールバックメソッドが現在のクラスに属する場合、コールバック配列の最初の要素は$thisです
        Timer::add(10, array($this, 'send'), array($to, $content), false);
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10秒後にメールを1回送信
    $mail = new Mail();
    $to = 'workerman@workerman.net';
    $content = 'こんにちは workerman';
    $mail->sendLater($to, $content);
};

// workerを実行
Worker::runAll();

8、定期関数をクラスの静的メソッドにする

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

class Mail
{
    // 注意これは静的メソッドで、コールバック関数はpublicでなければなりません
    public static function send($to, $content)
    {
        echo "メールを送信中 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10秒後にメールを1回送信
    $to = 'workerman@workerman.net';
    $content = 'こんにちは workerman';
    // クラスの静的メソッドを定期的に呼び出す
    Timer::add(10, array('Mail', 'send'), array($to, $content), false);
};

// workerを実行
Worker::runAll();

9、定期関数をクラスの静的メソッド(名前空間を持つ)

namespace Task;

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

class Mail
{
    // 注意これは静的メソッドで、コールバック関数はpublicでなければなりません
    public static function send($to, $content)
    {
        echo "メールを送信中 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10秒後にメールを1回送信
    $to = 'workerman@workerman.net';
    $content = 'こんにちは workerman';
    // 名前空間を持つクラスの静的メソッドを定期的に呼び出す
    Timer::add(10, array('\Task\Mail', 'send'), array($to, $content), false);
};

// workerを実行
Worker::runAll();

10、タイマー内で現在のタイマーを破棄($timer_idをuseで渡す)

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

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // カウント
    $count = 1;
    // $timer_idがコールバック関数内部に正しく渡されるために、$timer_idの前にはアドレス演算子 & を追加します
    $timer_id = Timer::add(1, function()use(&$timer_id, &$count)
    {
        echo "Timer run $count\n";
        // 10回実行した後に現在のタイマーを破棄
        if($count++ >= 10)
        {
            echo "Timer::del($timer_id)\n";
            Timer::del($timer_id);
        }
    });
};

// workerを実行
Worker::runAll();

11、タイマー内で現在のタイマーを破棄(引数方式で$timer_idを渡す)

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

class Mail
{
    public function send($to, $content, $timer_id)
    {
        // 一時的に現在のオブジェクトにcountプロパティを追加し、タイマーの実行回数を記録
        $this->count = empty($this->count) ? 1 : $this->count;
        // 10回実行した後に現在のタイマーを破棄
        echo "メールを送信中 {$this->count}...\n";
        if($this->count++ >= 10)
        {
            echo "Timer::del($timer_id)\n";
            Timer::del($timer_id);
        }
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    $mail = new Mail();
    // $timer_idがコールバック関数内部に正しく渡されるために、$timer_idの前にはアドレス演算子 & を追加します
    $timer_id = Timer::add(1, array($mail, 'send'), array('to', 'content', &$timer_id));
};

// workerを実行
Worker::runAll();