Udělejme si vlastní chat

Použití jazyka PHP si nyní ukážeme na komplexnějším příkladě, kterým bude jednoduchý chat. Chaty patří mezi velice oblíbené webové aplikace, a kromě ceny není důvod proč by neměly být oblíbené i ve své wapové podobě.

Na začátku práce s chatem si musí každý uživatel zvolit své jméno, pod kterým chce vystupovat. Následující příklad obsahuje jedno vstupní pole, do kterého lze zadat jméno. Jméno je jako parametr odesláno skriptu chat.php, který se stará o samostatné chatování.

Příklad 2. Stránka pro přihlášení do chatu – login.php

<? 
  Header("Content-Type: text/vnd.wap.wml");
  echo '<?xml version="1.0"?>';
?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
          "http://www.wapforum.org/DTD/wml_1.1.dtd">
<wml>
  <card title="Vitej v chatu!">
    <p>
      Pred vyuzitim chatu si musite zvolit jmeno: 
      <input name="jmeno"/>
    </p>
    <p>
      <a href="chat.php?jmeno=$(jmeno)#c2">Vstoupit</a>
    </p>
  </card>
</wml>          

Za URL adresou je přítomen ještě text `#c2'. Ten způsobí to, že po načtení vygenerované stránky se rovnou zobrazí karta s identifikátorem (atribut id) c2.

Než se ponoříme do zdrojového kódu jádra chatu, vysvětlíme si základní princip, na kterém pracuje. Jednotlivé zprávy v chatu se ukládají do textové souboru – jedna zpráva na jedné řádce. Na začátku řádky je vždy ještě uloženo jméno autora zprávy.

Skript chat.php se pak musí postarat o následující věci:

Příklad 3. Jádro chatu – chat.php

<? 
  Header("Content-Type: text/vnd.wap.wml");
  echo '<?xml version="1.0"?>';
    
  if ($zprava!="")
  {
    if (File_Exists("zpravy.txt"))
    {
      $zpravy = File("zpravy.txt");
    }

    $fp = FOpen("zpravy.txt", "w");
    FPutS($fp, "<b>$jmeno:</b> $zprava\n");
    for ($i=0; $i<10; $i++)
    {
      FPutS($fp, $zpravy[$i]);
    }
    FClose($fp);
  }

?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
          "http://www.wapforum.org/DTD/wml_1.1.dtd">
<wml>
  <card title="W@P Chat" id="c1">
    <p>
      Zprava: <input name="zprava"/><br/>
      <a href="chat.php?jmeno=$(jmeno)&amp;zprava=$(zprava)&amp;r=<?
        echo UniqId("")?>#c2">Odeslat</a>
      <br/>
      <a href="chat.php?jmeno=$(jmeno)&amp;r=<?echo UniqId("")?>#c2">
        Obnovit
      </a>
    </p>
  </card>
  <card title="W@P Chat" id="c2" 
        ontimer="chat.php?jmeno=$(jmeno)&amp;r=<?echo UniqId("")?>#c2">
    <timer value="200"/>
    <do type="accept" label="Nova zprava">
      <go href="#c1"/>
    </do>
    <?
      $fp = FOpen("zpravy.txt", "r");
      while ($radka = FGetS($fp, 512))
      {
        echo "<p>$radka</p>";
      }
      FClose($fp); 
    ?>
  </card>
</wml>          

Pojďme si nyní rozebrat jednotlivé části skriptu. Na začátku testujeme, zda nám přišla nějaká zpráva, kterou máme přidat do seznamu zpráv. Test provádíme pomocí podmínky if. Podmínka za if musí být vždy v závorkách, k porovnání dvou hodnot slouží operátor ==.

Pokud uživatel nějakou zprávu odeslal, musíme ji zapsat na začátek souboru. Pokud soubor existuje, načteme ho do pole:

if (File_Exists("zpravy.txt"))
{
  $zpravy = File("zpravy.txt");
}

Funkce File_Exists() testuje, zda zadaný soubor existuje. Pokud soubor existuje načteme ho pomocí funkce File() do pole s názvem $zpravy. Pole je speciální druh proměnné, která může obsahovat více hodnot najednou. V našem případě bude obsahovat každý prvek pole jeden řádek souboru a tedy i jednu zprávu.

Následující kód přidá na začátek souboru novou zprávu a za ní nakopíruje ty starší.

K otevření souboru pro zápis slouží funkce FOpen(). Jako její parametry musíme zadat název souboru a režim otevření (w označuje otevření pro zápis). Funkce nám vrátí identifikátor souboru, který se pak používá v dalších funkcích.

Aby šlo do souboru na serveru zapisovat, musíme mu správně nastavit práva. To jednoduše uděláme tak, že vytvoříme prázdný soubor zpravy.txt a nakopírujeme ho mezi skripty na serveru. Pak mu změníme atributy tak, aby do něj šlo zapisovat. Můžeme k tomu použít například Internet Explorer. Vybere soubor a otevřeme si jeho vlastnosti. V nich pak nastavíme právo zápisu pro všechny (viz obrázek 2).

Obrázek 2. Nastavení práv pro datový soubor

Novou řádku do souboru můžeme zapsat pomocí funkce FPutS(). Prvním parametrem je identifikátor souboru a druhým zapisovaný řetězec.

FPutS($fp, "<b>$jmeno:</b> $zprava\n");

Do souboru vložíme jednu řádku, okolo jména vložíme element b, za něj pak samotnou zprávu. Konec zprávy ukončíme pomocí znaku \n, který v textových řetězcích zastupuje konec řádky.

Nyní za novou zprávu zapíšeme starší zprávy. Zapisuje se přitom pouze deset nejnovějších zpráv.

for ($i=0; $i<10; $i++)
{
  FPutS($fp, $zpravy[$i]);
}

Příkaz for slouží k opakovanému provedení určitých příkazů, podobně jako ve WMLScriptu. Kopírujeme vždy jen posledních deset zpráv, aby nám soubor se zprávami zbytečně nenarůstal.

Nakonec soubor zavřeme pomocí funkce FClose().

Dále ve skriptu následuje statický WML kód pro první kartu. Ta obsahuje pouze vstupní pole pro zadání zprávy a odkazy pro odeslání nové zprávy a pro ruční obnovení zobrazených zpráv.

Jako součást odkazu se předává i paramet r. Jeho hodnotu generujeme dynamicky pomocí PHP funkce UniqId(). Ta vrací vždy jedinečné číslo. Tím že bude součástí URL adresy unikátní číslo, bude vždy prohlížeč načítat obsah stránky znovu ze serveru a nebude se jej snažit načíst z vyrovnávací paměti. Zobrazené zprávy budou vždy aktuální. Uvedený způsob je nejjednodušší a nejspolehlivější cestou k zakázání kešování stránek.

Odkaz je na konci doplněn znaky `#c2', aby se vždy skočilo na druhou kartu s výpisem zpráv.

Obrázek 3. Přihlášení k chatu

Druhá karta slouží k výpisu zpráv. Je na ní nastaven časovač na dvacet sekund. Po této době je karta automaticky znovu načtena (pomocí atributu ontimer). Zobrazí se tak případné nové zprávy od dalších uživatelů.

Na kartě je rovněž tlačítko, které umožní přechod na první kartu a zadání nové zprávy.

Obrázek 4. Chatování v plném proudu

Nakonec vypíšeme skriptem do karty všechny zprávy. Pomocí funkce FOpen() si nejprve otevřeme soubor, tentokráte pro čtení (režim r). Pomocí funkce FGetS() čteme jednotlivé řádky ze souboru. Nečteme však najednou nikdy více než 512 znaků (druhý parametr). Načtenou řádku ukládáme do proměnné $radka. Dokud není řádka prázdná provádějí se příkazy uvnitř těla příkazu while.

Příkaz

echo "<p>$radka</p>";

vypíše do generované WML stránky jeden odstavec, který bude obsahovat právě přečtenou zprávu ze souboru. Nakonec soubor opět uzavřeme.

© Jiří Kosek 2000-2001