3. díl - Návštěvní kniha přes WebSocket - Zprovoznění komunikace

PHP Návštěvní kniha přes WebSocket Návštěvní kniha přes WebSocket - Zprovoznění komunikace

V minulém tutoriálu seriálu Real-time návštěvní kniha přes WebSocket jsme implementovali jednoduchý Node.js server a začali s PHP serverem, kde jsme vytvořili hlavní třídu a autoloader. Dnes budeme pokračovat vytvořením třídy pro volání Node.js serveru a přidáme si slíbenou šablonu.

PHP/classes/Web­SocketApi.php

Tato třída slouží pro volání Node.js serveru a získání odpovědi, zda se přeposlání požadavku přes WebSockets na další klienty povedlo. Bude obsahovat jednu metodu a to "sendSocket()" s parametry "$channel", "$data" a tři privátní proměnné:

  • "$password" - stejné heslo jako v souboru "server.js"
  • "$ip" - localhost
  • "$port" - 4000

Ukažme si kód třídy, jako vždy si ho hned popíšeme:

<?php

class WebSocketApi {

    private $password = "d$0awd6$5ZVawdIhlawdZJr8xwadtRFnSlbRX2.$2a$0awd6$5ZVIhawdlZJwdr8xtRFnS72lbRX2.Dsylt5.YSi1BzzqawdBt3rsBawdxYQMYIqsFe",
        $ip = "localhost",
        $port = 4000;

    public function sendSocket($channel, $data) {

        $Url = "http://$this->ip:$this->port";

        $ch = curl_init();

        $POST = ["channel" => $channel, "password" => $this->password, "data" => json_encode($data, JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_QUOT)];

        $POST_string = null;

        foreach ($POST as $key => $value) {
            $POST_string .= $key.'='.$value.'&';
        }
        rtrim($POST_string, '&');

        curl_setopt($ch, CURLOPT_URL, $Url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch,CURLOPT_POST, count($POST));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $POST_string);

        $response = curl_exec($ch);
        curl_close($ch);

        return $response == "true";
    }

}

Metoda "sendSocket()" obsahuje proměnnou "$Url", která sjednotí IP adresu a port do jednoho. Dále načítáme curl (technologie pro posílání webových požadavků z PHP, na některých webhostinzích ji je třeba aktivovat) a vytváříme pole s nastavením pro curl. Kousek níže vytváříme pole s POST daty. Cyklus přemění POST data na string, funkcí rtrim() na konci odstraníme poslední "&". Nyní již jen trochu nastavíme curl a do proměnné si uložíme výsledek požadavku na Node.js server. Následně zavřeme curl a vrátíme true pokud jsme od serveru dostali řetězec "true", v opačném případě vrátíme false jako neúspěch.

Abychom mohli náš PHP server vyzkoušet, potřebujeme ještě chybějící šablonu. Pojďme si ji přidat.

PHP/template.phtml

Obsah souboru bude zatím pouhá html kostra s jQuery, socket.io, Font Awesome a vlastním stylem, který také vytvoříme. Soubor bude vypadat nějak takto:

<!DOCTYPE html>
<html>
<head lang="cs-cz">
    <meta charset="UTF-8">
    <meta name="author" content="Patrik Smělý(SogoCZE)">
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="Realtime Kniha návštěv">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Realtime Kniha návštěv</title>
    <base href="localhost">
    <link rel="stylesheet" type="text/css" href="/css/style.css">
    <link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" charset="UTF-8"></script>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js" charset="UTF-8"></script>
</head>
<body>
    <h1>Realtime Kniha návštěv</h1>
</body>
</html>

PHP/CSS/style.css

K šabloně potřebujeme i nějaké ty styly. Vytvoříme tedy adresář "css" v našem PHP adresáři a v něm ještě soubor "style.css". Ten bude zatím obsahovat jen pár základních věcí a to:

* {
    padding: 0 0 0 0;
    margin: 0 0 0 0;
    box-sizing: border-box;
}
body {
    background-color: #DDDDDD;
    color: black;
    font-size: 14px;
    font-family: Helvetica Neue, Helvetica, Arial;
}

Jdeme tedy konečně vyzkoušet náš PHP systém a celé websocket API! Do metody "mainMethod()" ve třídě "MainClass" přidáme následující kód:

PHP/classes/Ma­inClass.php

public function mainMethod() {

    $WebSocketApi = new WebSocketApi();
    if ($WebSocketApi->sendSocket("Test", ["name" => "Patrik", "message" => "testing"]) === true) {
        echo("Povedlo se! Nodejs vrací true!");
    } else {
        echo("Něco se nepovedlo! Node.js nevrací true!");
    }

    echo $this->render();
}

Vytvoříme instanci našeho websocketového API a přidáme podmínku, ve které budeme volat metodu "sendSocket()". Parametry jsou Kanál a [data]. Jako kanál zvolíme např. řetězec "Test" a do dat dáme například ["name" => "Patrik", "message" => "testing"].

Vraťme se zpět k naší podmínce. Pokud tato metoda vrátí true, vypíšeme "Povedlo se! Node.js vrací true!“ Když tomu tak není, vypíšeme "Něco se nepovedlo! Node.js nevrací true!".

Nyní spustíme Apache v XAMPPu a přes prohlížeč přejdeme na adresu "localhost". Měli bychom dostat následující výsledek:

Dotaz z PHP na Node.js

Hm, to nám toho ale moc neřeklo že? Zkusme si tedy trochu toho real-timu. Přejdeme do template.phtml a pod <h1> nadpis si vložíme div s třídou "messages". Pod něj vložíme script, který bude došlé zprávy v reálném čase přidávat do stránky.

PHP/template.phtml

<div class="messages"></div>
<script type="application/javascript">

    var Sockets = io.connect('localhost:4000');

    Sockets.on('Test', function(data) {

        $('.messages').append("<span>" + data.name + ": " + data.message + "</span><br/>");

    });

</script>

Pomocí metody io.connect() se připojíme k serveru a budeme naslouchat na daném kanálu. Parametrem metody connect() je IP adresa a port. Tímto připojíme uživatele k našemu serveru. Jako callback má naslouchací metoda on() nastavenou funkci, která v parametrech přijímá data. Tu využijeme pro výpis dat z PHP serveru. V callback funci připojíme do našeho divu spany s proměnnými data.name a data.message. Tím do stránky přidáme došlé zprávy. Měli byste dostat následující výsledek:

Real-time obnovení stránky přes PHP a Node.js

Když si nyní web načteme 2x vedle sebe a jeden obnovíme, na druhém se okamžitě ukáže naše zpráva. To znamená, že PHPčko odeslalo data do Node.js a ten obeslal uživatele a vynutil obnovení stránky. Komunikujeme tedy z PHP s klienty, aniž by zavolali PHP požadavek. No není to úžasné? :) Naše API funguje jak má. V příštích dílech aplikaci upravíme do plnohodnotné real-time knihy návštěv nebo chatu, chcete-li projekt tak nazývat.


 

  Aktivity (1)

Článek pro vás napsal Patrik Smělý (SogoCZE)
Avatar
Autor se věnuje front-end i back-end vývoji webových stránek, nejvíce pracuje s jazykem PHP a Javascript. Rád se učí nové věci a někdy strčí nos i do 3D / 2D grafiky.

Jak se ti líbí článek?
Celkem (3 hlasů) :
4.666674.666674.666674.666674.66667


 



 

 

Komentáře
Zobrazit starší komentáře (1)

Avatar
Patrik Smělý (SogoCZE)
Tým ITnetwork
Avatar
Patrik Smělý (SogoCZE):

Ahoj, problém s "./" a "/" jsem neměl protože funguji na windows platformně vzhledem k tomu že jsi na OSX což je jakoby pod linuxem tak to asi bude tím linuxem protože jsem stejný problém měl na mém linuxovém serveru tak to vidím že je to opravdu linuxem :).

Ahoj nejsem si jist ale je to možná portem na kterém nodejs jede, funguje ti stránka s bad requestem na http://localhost:4000 jeslti ne tak se opravdu jedná o problém s portem proto změn v serverovém scriptu port třeba na 3000. On je problém že OSX si možná zabírá port 4000 pro nějakou službu :).

Doufám že jsem pomohl a děkuji za komentář :).

Odpovědět 30.11.2015 16:18
PHP můj oblíbený jazyk......
Avatar
Odpovídá na Patrik Smělý (SogoCZE)
Dominik Dosoudil:

Ahoj,
zkoušel jsem 4000, 4100 a teď i 3000. Všechny porty háží Bad request i "Povedlo se! Nodejs vrací true!".
Avšak zprávy stále nechodí.
Ještě jsem zapomněl napsat, že mi to do body háže znak "1" který si nedokáži vysvětlit :D. Napadlo mě, že by to mohlo být true, ale nikde nevidím žádný výpis, který by to tam mohl dávat.

 
Odpovědět 30.11.2015 19:54
Avatar
reddi
Člen
Avatar
reddi:

Ahoj, jedničku to tam hází z metody mainMethod(), jelikož je na konci echo a include šablony se provede.

 
Odpovědět 5. dubna 16:21
Avatar
shaman
Člen
Avatar
Odpovídá na Patrik Smělý (SogoCZE)
shaman:

Zaujimavy koncept.
Ako to planujes osetrit aby sa na ten websocket nemohol napojit hocikto a pocuvat?

Odpovědět 18. července 0:02
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Patrik Smělý (SogoCZE)
Tým ITnetwork
Avatar
Odpovídá na shaman
Patrik Smělý (SogoCZE):

Ahoj,

Pokud si myslel například ze svého webu kde budeš mít socket.io klienta tak je to jednoduché, ošetření je prováděno přes originy, jednoduše na serverové straně (NodeJs) nastavíš že se klienti můžou připojit jen z určité ip:portu / domény:portu implementace pak vypadá následovně. (Ze základu je připojení povoleno odkudkoliv)

io.set('origins', 'www.example.com:80');
Editováno 18. července 0:27
Odpovědět 18. července 0:26
PHP můj oblíbený jazyk......
Avatar
shaman
Člen
Avatar
Odpovídá na Patrik Smělý (SogoCZE)
shaman:

uzivatel nema origin. Uzivatel ma IP adresu. Na tej istej IP adrese je kopa ludi ktory nemaju alebo by nemali mat pristup k websocketu? V pripade knihy navstev je to ok, ale co ked budem robit chat? Ako by si to osetril?

Odpovědět 18. července 9:45
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na shaman
David Čápka:

Uživatel chatu bude registrovaný, bude mít nějaké ID.

Odpovědět  +1 18. července 9:51
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
shaman
Člen
Avatar
Odpovídá na David Čápka
shaman:

takze id bude mat uzivatel nastavene napr. v session
a websocket bude mat zoznam povolenych ID ktorym ma propagovat spravy?

Odpovědět 18. července 10:06
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovědět  +2 18. července 11:00
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Patrik Smělý (SogoCZE)
Tým ITnetwork
Avatar
Odpovídá na shaman
Patrik Smělý (SogoCZE):

Přímo uživatel mít origin nebude ale klient z jakého se připojuje origin má, takže pokud se uživatel připojí z webového klienta tak bude mít origin dané webové stránky, pokud se ale připojí například z localhostu - přes nějaký program či prostě z webu na localhostu tak jako origin bude mít svojí ip adresu.

Jinak jak psal David Čápka, při pokročilém ošetření je potřeba využít nějaký token, který bude vždy posílat uživatel při svém prvním připojením, server si následně daný token ověří a na základě toho bude dále posílat či neposílat tomuto uživateli sockety.

Odpovědět 18. července 13:48
PHP můj oblíbený jazyk......
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 11. Zobrazit vše