Informatyka dla klasy IIIK

PHP: Prosta ankieta z grafiką

Na dzisiejszych zajęciach utworzymy w PHP proste narzędzie do zbierania opinii od użytkowników. Wykorzystamy formularz oraz proste skrypty PHP, które będą zbierały głosy od użytkowników i prezentowały wyniki w sposób graficzny. Wyniki głosowania będą przechowywane w pliku na serwerze. Zanim rozpoczniemy, wyczyść katalog C:\wamp\www. Następnie zapisz w nim poniższy obrazek:

Nie zmieniaj nazwy obrazka, niech zostanie pool.gif.

Uruchom Notatnik Windows i utwórz w nim 5 wierszy zawierających cyfrę 0:

0
0
0
0
0

Plik zapisz w katalogu C:\wamp\www pod nazwą cnt.txt. Będziemy w nim zliczać oddane w ankiecie głosy.

Uruchom MS Expression Web 4 i pod kierunkiem nauczyciela utwórz formularz z 5 opcjami:

Nasi kandydaci

Kowalski Jan
Barański Tomasz
Fido Mariusz
Żonkil Magdalena
Kawa Justyna

 

Zobacz wyniki

We własnościach formularza ustaw:

 

<body>
<div align="center">
<table cellpadding="4" cellspacing="0" style="background-color: #CCCCCC">
    <tr>
        <td>
            <h3 style="text-align: center">Nasi kandydaci</h3>
            <form method="post" action="pool.php">
                <p style="text-align: left">
                    <input type="checkbox" name="C0" value="ON"/>Kowalski Jan<br/>
                    <input type="checkbox" name="C1" value="ON"/>Barański Tomasz<br/>
                    <input type="checkbox" name="C2" value="ON"/>Fido Mariusz<br/>
                    <input type="checkbox" name="C3" value="ON"/>Żonkil Magdalena<br/>
                    <input type="checkbox" name="C4" value="ON"/>Kawa Justyna
                </p>
                <p style="text-align: center">
                    <input type="submit" value="Głosuj" name="B1" />&nbsp;
                    <input type="reset" value="Resetuj" name="B2" />
                </p>
            </form>
            <p style="text-align: center"><a href="show.php">Zobacz wyniki</a></p>
       </td>
    </tr>
</table>
</div>
</body>

 

Plik zapisz w katalogu C:\wamp\www pod nazwą index.html.

Otwórz w MS Expression Web 4 nowy plik PHP. W sekcji <body> utwórz skrypt PHP:
<div align="center">
<?php
$votes = file("cnt.txt",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($votes as $i => $v) if(isset($_REQUEST["C$i"])) $votes[$i]++;
$h = fopen("cnt.txt","w");
foreach($votes as $v) fwrite($h,$v."\n");
fclose($h);
echo "<p>Dziękujemy za oddanie głosu</p>";
echo "<p><a href='index.html'>Powrót do strony głównej</a></p>";
?>
</div>

Plik zapisz w katalogu C:\wamp\www pod nazwą pool.php

Otwórz w MS Expression Web 4 nowy plik PHP. W sekcji <body> utwórz skrypt PHP:
<div align="center">
<h2>Wyniki głosowania</h2>
<?php 
$votes = file("cnt.txt",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$sum = 0;
foreach($votes as $v) $sum += $v;
if(!$sum) echo "<p>Nie oddano jeszcze żadnego głosu</p>\n";
else
{
  $c = array("Kowalski Jan","Barański Tomasz","Fido Mariusz","Żonkil Magdalena","Kawa Justyna");
  echo "<table>\n";
  foreach($votes as $i => $v)
  {
     $w = $v * 256 / $sum;
     echo "<tr><td>".$c[$i]."</td><td>Liczba głosów = $v</td><td><img src='pool.gif' height='10' width='$w'/></td></tr>\n";
  }
  echo "</table>\n";
}
echo "<p><a href='index.html'>Powrót do strony głównej</a></p>\n";
?>
</div>

Plik zapisz w katalogu C:\wamp\www pod nazwą show.php

Podsumowanie

$t = file(plik,opcje) wczytuje podany plik z dysku serwera do zmiennej $t jako tablicę
FILE_IGNORE_NEW_LINES : do końców elementów nie będą dołączane znaki \n
FILE_SKIP_EMPTY_LINES : w tablicy nie znajdą się puste wiersze
foreach($t as $v) tworzy pętlę, która wykona się tyle razy, ile elementów posiada tablica $t. W każdym obiegu pętli w zmiennej $v znajdzie się kolejny element tablicy.
foreach($t as $i => $v) jak wyżej, w zmiennej $i znajdzie się indeks elementu, w zmiennej $v element tablicy
isset($v) zwraca true, jeśli zmienna $v została ustawiona w programie. Tutaj sprawdzamy tą funkcją, czy do skryptu php przekazano stan opcji z formularza. Jeśli tak, to tablica $_REQUEST zawiera element o indeksie będący nazwą opcji w formularzu.
$h = fopen(plik,tryb) otwiera plik na dysku serwera. Tryb "r" oznacza otwarcie do odczytu, tryb "w" oznacza otwarcie do zapisu. Gdy plik zostanie otwarty, w zmiennej $h otrzymujemy tzw. uchwyt lub dojście do pliku. Wartość ta jest wykorzystywana w operacjach plikowych.
fwrite($h,dane) zapisuje w otwartym pliku dane.
fclose($h) zamyka plik

Uwaga: podane tutaj rozwiązanie nie jest bezpieczne. W rzeczywistych warunkach należałoby dodatkowo zablokować dostęp do pliku na czas jego przetwarzania w skrypcie. Inaczej głosy mogą być źle zliczane (gdy np. zagłosuje jednocześnie kilku użytkowników). Zagadnienie jest nieco skomplikowane, dlatego zostało tutaj pominięte. Jeśli interesuje cię to, poszukaj informacji o funkcji flock().

Aplikacja nie sprawdza także, czy dany użytkownik głosował tylko jeden raz. Aby to zrobić należałoby zapamiętywać w pliku na dysku adresy IP, skąd nadszedł formularz, i sprawdzać, czy dany adres IP jest nowy (wyniki głosowania dopisujemy do ankiety tylko dla nowych adresów IP). Nie jest to proste, dlatego to zagadnienie również pominięto.

(Dla zdolnych) Gdybyś jednak był bardzo zainteresowany tym zagadnieniem, to przeanalizuj poniższy skrypt (sam go stosuję w tym serwisie do statystyki odwiedzin):

 
<?php

// Skrypt zawiera funkcje odczytujące poprawny numer IP użytkownika
//-----------------------------------------------------------------

// Funkcja zwraca true, jeśli podany adres IP jest poprawny
//---------------------------------------------------------
function validip($ip)
{
  if(!empty($ip) && ip2long($ip)!=-1)
  {
    $reserved_ips = array
    (
      array('0.0.0.0','2.255.255.255'),
      array('10.0.0.0','10.255.255.255'),
      array('127.0.0.0','127.255.255.255'),
      array('169.254.0.0','169.254.255.255'),
      array('172.16.0.0','172.31.255.255'),
      array('192.0.2.0','192.0.2.255'),
      array('192.168.0.0','192.168.255.255'),
      array('255.255.255.0','255.255.255.255')
    );
    foreach($reserved_ips as $r)
    {
      $min = ip2long($r[0]);
      $max = ip2long($r[1]);
      if((ip2long($ip) >= $min) && (ip2long($ip) <= $max)) return false;
    }
    return true;
  }
  else return false;
}

// Funkcja zwraca adres IP użytkownika
//------------------------------------
function getip()
{
  if (isset($_SERVER["HTTP_CLIENT_IP"]))
  {
    if (validip($_SERVER["HTTP_CLIENT_IP"])) return $_SERVER["HTTP_CLIENT_IP"];
  }
  if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
  {
    foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $ip) if (validip(trim($ip))) return $ip;
  }
  if (isset($_SERVER["HTTP_X_FORWARDED"]) && validip($_SERVER["HTTP_X_FORWARDED"]))
    return $_SERVER["HTTP_X_FORWARDED"];
  elseif (isset($_SERVER["HTTP_FORWARDED_FOR"]) && validip($_SERVER["HTTP_FORWARDED_FOR"]))
    return $_SERVER["HTTP_FORWARDED_FOR"];
  elseif (isset($_SERVER["HTTP_FORWARDED"]) && validip($_SERVER["HTTP_FORWARDED"]))
    return $_SERVER["HTTP_FORWARDED"];
  elseif (isset($_SERVER["HTTP_X_FORWARDED"]) && validip($_SERVER["HTTP_X_FORWARDED"]))
    return $_SERVER["HTTP_X_FORWARDED"];
  else
    return $_SERVER["REMOTE_ADDR"];
}

$adres_ip = getip();
?>

 

Gdy umieścisz ten skrypt na swojej stronie, to w zmiennej $adres_ip znajdzie się numer IP komputera użytkownika, który pobiera tę stronę z serwera (pamiętaj, że skrypt PHP jest uruchamiany przez serwer zanim strona zostanie wysłana do sieci). Spróbuj wykorzystać to w swojej aplikacji. Otrzymany numer IP należy porównać z numerami IP przechowywanymi w pliku, a jeśli jest nowy, to należy go dopisać na końcu tego pliku i przetworzyć ankietę. Jeśli numer IP już jest w pliku, to aplikacja nie powinna podejmować działań, ewentualnie można wypisać tekst "Już głosowałeś".

 



List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2017 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.