April 13, 2013

FuelPHPでWebSocketを扱うパッケージを作りました

追記: 2013/04/23
簡単なサンプルを公開しています。
http://fuelratchet.madroom.org/

追記: 2013/04/21
一部、内容が古くなっている箇所があります。最新の内容は、GitHubのREADME.mdに記載しています。

--

以前、以下の記事を書きました。

PHPでWebSocketを用いたチャットサンプル
http://madroom-project.blogspot.jp/2013/04/phpwebsocket.html

今回、上記で使用しているRatchetを組み込んだ、FuelPHPのパッケージを作ってみました。
* 以下、Ratchetパッケージとします。
https://github.com/mp-php/fuel-packages-ratchet


当記事では、Ratchetパッケージを、ローカル環境で動作させるまでの手順について書いておきます。


(1) ZeroMQのインストール
まず、ZeroMQをインストールします。RatchetのWampServerで使用します。(当記事のサンプルでは使用しません。)
各OSでのインストール手順は、以下になります。
Linux(Ubuntu): http://madroom-project.blogspot.jp/2013/04/ubuntu-phpzeromq.html
Mac(MAMP): http://madroom-project.blogspot.jp/2013/04/mampmaczeromq.html
Win(XAMPP): http://madroom-project.blogspot.jp/2013/04/xamppwindowszeromq.html

正しくインストール出来たかは、phpinfoで確認ができます。

ZeroMQは、Webとコマンド、双方で有効にして下さい。(php.iniが異なる場合が有るので注意です。)


(2) FuelPHPのインストール
FuelPHPをgit cloneするなりzipでDLするなりして、適切な場所に配置して下さい。


(3) Ratchetパッケージのインストール
Ratchetパッケージをgit submoduleするなりzipでDLするなりして、fuel/packages/ratchetとして配置します。
submoduleとして追加する場合、以下で可能です。
# FuelPHPのプロジェクトルートで実行
$ git submodule add git://github.com/mp-php/fuel-packages-ratchet.git fuel/packages/ratchet


(4) Ratchetパッケージが必要とする外部ライブラリのインストール
以下のコマンドを実行します。
$ cd fuel/packages/ratchet # Ratchetパッケージに移動
$ php composer.phar install # 必要な外部ライブラリのインストール
* (1)のZeroMQが正しくインストールされていないと、エラーが発生します。


(5) 簡単なメッセージ送信機能を作ります。
fuel/app/config/config.php の always_load.packages にRatchetパッケージを追加します。
'always_load'  => array(
    'packages'  => array(
        'ratchet',
fuel/app/classes/my/ratchet/ws.php を作成します。
<?php

require PKGPATH.'ratchet/vendor/autoload.php';

class My_Ratchet_Ws extends Ratchet_Ws
{

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(\Ratchet\ConnectionInterface $conn) {
        $this->clients->attach($conn);
    }

    public function onClose(\Ratchet\ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }

    public function onMessage(\Ratchet\ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            if ($from != $client) {
                $client->send(Security::htmlentities($msg));
            }
        }
    }

    public function onError(\Ratchet\ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }

}

/* end of file ws.php */
public/ws.htmlを作成します。
* 実際にはControllerから呼び出すViewで使用されるviewファイルになります。
* 'example.com'の箇所は、置換して下さい。
<html>
<head>
<script>
var conn = new WebSocket('ws://example.com:8001');
// 接続時
conn.onopen = function(e) {
    console.log("Connection established!");
};
// メッセージ受信時
conn.onmessage = function(e) {
    console.log(e.data);
};
function send() {
    var msg = document.getElementById("text").value;
    conn.send(msg);
}
</script>
</head>
<body>
<input type="text" id="text" />
<input type="button" id="button" value="Send" onclick="send();" />
</body>
</html>

(6) タスクから起動します。
* 第二引数のポート番号は、適宜置換して下さい。その際、(5)のws.htmlに書いてあるポート番号も変更して下さい。
$ php oil r ratchet:ws My_Ratchet_Ws 8001
* 終了はctrl + cです。
* 商用環境では、Supervisorでの起動を推奨します。その方法は、改めて書きたいと思います。


(7) 二つのブラウザから、(5)のws.htmlにアクセスします。
コンソールに'Connection established!'と表示されることを確認します。


(8) どちらかのブラウザから、メッセージを入力してSendボタンを押します。
もう一方のブラウザのコンソールに内容が表示されることを確認します。


P.S.
僕自身、WebSocketについての学習をこれから始めるので、色々と手探り状態です。今後は、以下に備忘録を兼ねたサンプルを追加していこうと思っています。
https://github.com/mp-php/fuel-ratchet-samples

とりあえず、Ratchetサーバ側とでのSession共有方法と、RatchetのWampServerあたりをなる早で作ろうかなと思っています。

No comments:

Post a Comment