PHP/Umfrage

Aus Mikiwiki
< PHP
Version vom 11. Februar 2009, 17:05 Uhr von Michi (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Die Ergebnisse von Umfragen werden üblicherweise erst ausgegeben, wenn der Nutzer sich beteiligt. Die hier vorgestellte Anwendung "Umfrage" nutzt eine Mysql-Datenbank mit einer einzigen Tabelle. Ausser dem HTML-Formular ist eine einfache Auswertung Bestandteil des Programms.

Das Programm besteht aus vier Dateien:

  • "open.inc.php" enthält die Daten für die Datenbankverbindung
  • "umfrage.css" - Stylesheet
  • "umfrage.php" - das Umfrageformular in reinem HTML
  • "auswertung.php" - die Auswertung

Datenbankstruktur

Die hier vorgestellte Anwendung "Umfrage" nutzt eine Mysql-Datenbank mit einer einzigen Tabelle namens "umfrage".

# Name     umfrage.sql

CREATE TABLE umfrage (
  bundesland varchar(30),
  standort   int(11),
  onlinezeit int(11),
  zugang     int(11),
  kosten     int(11),
  bestellt   char(2),
  summe      double,
  service    int(11),
  id         int(11) NOT NULL auto_increment,
  PRIMARY KEY (id)
);

Das Umfrageformular

<!-- Name     umfrage.php -->
<html>
<head>
  <title>Umfrage</title>
  <link rel="stylesheet" type="text/css" href="umfrage.css">
</head>
<body bgcolor="#EEEEEE">
<h1>Umfrage</h1>
<h2>Herzlich willkommen zu unserer neuen Umfrage</h2>
<div class=text>
<p>Um die Ergebnisse der Umfrage ansehen zu können, füllen Sie alle Fragen aus und klicken Sie auf absenden.</p>
<p>Die Umfrage ist selbstverständlich anonym.</p>
<form action="auswertung.php" method="post">
  <table bgColor="Silver" border=0 cellpadding=1 cellspacing=2 width=100%>
    <tr>
      <td bgColor="#eeeeee" colSpan=2><b>Zuerst Fragen nach der Herkunft</b></td>
    </tr>
    <tr>
      <td bgColor=#ffe4b5>Aus welchem Bundesland kommen Sie?</td>
      <td bgColor=#ffe4b5>
        <select name=bundesland>
          <option >Baden-Württemberg</option>
          <option >Bayern</option>
          <option selected>Berlin</option>
          <option >Brandenburg</option>
          <option >Bremen</option>
          <option >Hamburg</option>
          <option >Hessen</option>
          <option >Mecklenburg-Vorpommern</option>
          <option >Niedersachsen</option>
          <option >Nordrhein-Westfalen</option>
          <option >Rheinland-Pfalz</option>
          <option >Saarland</option>
          <option >Sachsen</option>
          <option >Sachsen-Anhalt</option>
          <option >Schleswig-Holstein</option>
          <option >Thüringen</option>
        </select>
      </td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Von wo aus gehen Sie ins Internet?</td>
      <td bgColor="#ffe4b5">
        <input checked name=standort type=radio value=1> zu Hause
        <input name=standort type=radio value=2>im Büro
        <input name=standort type=radio value=3>Uni/Schule
	<input name=standort type=radio value=3>zu Hause und Büro
      </td>
    </tr>
    <tr>
      <td bgColor="#eeeeee" colspan=2><b>Fragen zur Benutzung des Internet</b></td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Wie viele Stunden pro Woche sind Sie online?</td>
      <td bgColor="#ffe4b5">
        <input name=onlinezeit type=text>Stunden durchschnittlich
      </td>
    </tr>
      <td bgColor="#ffe4b5">Welche Art Zugangstechnik haben Sie?</td>
      <td bgColor="#ffe4b5">
        <input name=zugang type=radio value=1> ISDN 
        <input checked name=zugang type=radio value=2> Modem
        <input name=zugang type=radio value=3> LAN/Gateway
      </td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Wie hoch sind ca. Ihre Online-Kosten?</td>
      <td bgColor="#ffe4b5">
        <input name=kosten type=text> &euro; (Provider+Telefon)
      </td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Haben Sie schon mal was online gekauft?</td>
      <td bgColor="#ffe4b5">
        <input name=bestellt type=checkbox value=on>Ja, ich habe online bestellt und bezahlt
      </td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Wie viel haben Sie im letzten Jahr online gekauft?
      <td bgColor="#ffe4b5"><input name=summe type=text> &euro; (ca. Gesamtwert)</td>
    </tr>
    <tr>
      <td bgColor="#ffe4b5">Wie zufrieden waren Sie mit dem Service?</td>
      <td bgColor="#ffe4b5">&nbsp;
        <input name=service type=radio value=1>1 
        <input name=service type=radio checked value=2>2 
        <input name=service type=radio value=3>3
        <input name=service type=radio value=4>4
        <input name=service type=radio value=5>5  
        (Schulnoten) 
      </td>
    </tr>
  </table>
  <p><input name=submit1 type=submit value="Absenden und Ergebnisse ansehen">&nbsp;&nbsp;&nbsp; 
     <input name=reset1 type=reset value="Neueingabe"></p>
</form>
</div>
</body>
</html>

Auswertung

Die Auswertung schreibt die Formulardaten in die Datenbank und fragt die aktualisierten Daten gleich anschliessend ab.

<?php
## Name     auswertung.php

## Die Formulardaten werden im Array "$_POST" erwartet. Wenn bestimmte
## Felder nicht ausgefüllt wurden, werden die Variablen auf 0 oder ""
## gesetzt oder es erfolgt eine Umleitung auf das Formular. Der Nutzer
## kann damit fehlerhaft ausgefüllte Formulare nicht absenden.
$bundesland = isset($_POST['bundesland']) ? $_POST['bundesland'] : "";
$standort   = isset($_POST['standort'])   ? $_POST['standort']   : "";
$onlinezeit = isset($_POST['onlinezeit']) ? $_POST['onlinezeit'] : 0;
$zugang     = isset($_POST['zugang'])     ? $_POST['zugang']     : 0;
$kosten     = isset($_POST['kosten'])     ? $_POST['kosten']     : 0;
$bestellt   = isset($_POST['bestellt'])   ? $_POST['bestellt']   : 0;
$summe      = isset($_POST['summe'])      ? $_POST['summe']      : 0;
$service    = isset($_POST['service'])    ? $_POST['service']    : 0;
if ($bundesland=="" or $standort=="" or $onlinezeit=="") 
{
  header("Location: {$_SERVER['HTTP_REFERER']}");
  exit;
}
## Verbindung zur Datenbank herstellen.
include ("open.inc.php");
## Die Formulardaten werden in die Tabelle eingefügt.
$query  = "INSERT INTO umfrage (bundesland, standort, onlinezeit,
             zugang, kosten, bestellt, summe, service)
           VALUES (\"$bundesland\", $standort, $onlinezeit, $zugang, 
             $kosten, \"$bestellt\", $summe, $service)";
mysql_query($query, $connection);
?>

<html>
<head>
  <title>Auswertung</title>
  <link rel="stylesheet" type="text/css" href="umfrage.css">
</head>
<body bgcolor="#EEEEEE">
<h1>Auswertung der Umfrage</h1>
<div class=text>
<p>Die Ergebnisse sind eine Zusammenfassung der Angaben aller bisherigen Teilnehmer.</p>
<p>
<table bgcolor="silver" border="0" cellpadding="1" cellspacing="2" width="100%">
  <tr>
    <th>Fragestellung</th>
    <th>Ergebnis</th>
  </tr>
  <tr>
    <td valign="top" bgcolor=#ffe4b5>Aus welchen Bundesländern<br />kamen wieviele Besucher?</td>
    <td bgcolor="#ffe4b5" valign="top">
      <table border="1" cellpadding="2" cellspacing="0" bordercolor="white" width="100%">
        <?php
        ## Ermitteln der Anzahl Nutzer pro Bundesland. Feld 0 enthält
        ## die Anzahl (berechnet mit COUNT) und Feld 1 den Namen des
        ## Bundeslands. Um die Länderliste eindeutig zu machen, wird
        ## sie mit GROUP BY gruppiert.
        $query = "SELECT COUNT(bundesland), bundesland FROM umfrage GROUP BY bundesland";
        $rs    = mysql_query($query, $connection);
        while ($row = mysql_fetch_row($rs))
        {
          echo <<<ROW
          <tr>
            <td>$row[1]</td>
            <td>$row[0]</td>
          </tr>
ROW;
        }
        ?>
      </table>
    </td>
  <tr>
    <td valign="top" bgcolor=#FFE4b5>Wo steht der Rechner?</td>
    <td bgcolor=#FFE4b5 valign="top">
      <?php
      ## Auswertung der Nutzungsplätze.
      $query = "SELECT COUNT(standort), standort FROM umfrage GROUP BY standort";
      $rs    = mysql_query($query, $connection);
      $zh    = $ib = $us = 0;
      ## Zusätzlich wird hier eine prozentuale Berechnung angeschlossen.
      ## Dazu werden die Werte einzeln ausgewählt (switch) und dann mit
      ## der Summe berechnet. Durch die GROUP BY-Bedingung tritt jede 
      ## Variante nur einmal auf, die Schleife wird also tatsächlich nur
      ## dreimal durchlaufen.
      while ($row = mysql_fetch_row($rs)) 
      {
        switch ($row[1])
        {
          case 1: 
            $zh = (int) $row[0];
            break;
          case 2:
            $ib = (int) $row[0];
            break;
          case 3:
            $us = (int) $row[0];
            break;
         }
       }
       $summe = $zh + $ib + $us;
       $p_zh = sprintf("%0.2f", $zh / $summe * 100);
       $p_ib = sprintf("%0.2f", $ib / $summe * 100);
       $p_us = sprintf("%0.2f", $us / $summe * 100);
       echo <<<INFO1
       $zh Rechner zu Hause = $p_zh %<br />
       $ib Rechner im Büro = $p_ib %<br />
       $us Rechner in UNI/Schule = $p_us %
INFO1;
      ?>
    </td>
  </tr>
  <tr>
    <td valign="top" bgcolor=#FFE4b5>Welche Zugangstechnik wird benutzt?</td>
    <td bgcolor=#FFE4b5 valign="top">
      <?php
      $query = "SELECT COUNT(zugang), zugang FROM umfrage GROUP BY zugang";
      $rs    = mysql_query($query, $connection);
      $mo    = $id = $ln = 0;
      while ($row = mysql_fetch_row($rs))
      {
        switch ($row[1])
        {
          case 1:
            $id = (int) $row[0];
            break;
          case 2:
            $mo = (int) $row[0];
            break;
          case 3:
            $ln = (int) $row[0];
        }
      }
      $summe = $mo + $id + $ln;
      $p_id  = sprintf("%0.2f", $id / $summe * 100);
      $p_mo  = sprintf("%0.2f", $mo / $summe * 100);
      $p_ln  = sprintf("%0.2f", $ln / $summe * 100);
      echo <<<INFO2
      $id ISDN        = $p_id %<br />
      $mo Modem       = $p_mo %<br />
      $ln LAN/Gateway = $p_ln %
INFO2;
      ?>
    </td>
  </tr>
  <tr>
    <td bgcolor=#ffe4b5 nowrap>Wie viele Stunden sind Sie im Schnitt online?</td>
    <td bgcolor=#ffe4b5>
      <?php
      ## Die durchschnittlich beim Surfen verbrachte Zeit wird direkt in der
      ## Datenbank über alle Felder berechnet.
      $query = "SELECT AVG(onlinezeit) FROM umfrage";
      $rs    = mysql_query($query, $connection);
      $row   = mysql_fetch_row($rs);
      printf("Im Durchschnitt wird %0.2f Stunden pro Monat gesurft", $row[0]);
      ?>
    </td>
  </tr>
  <tr>
    <td bgcolor=#FFE4b5>Wie hoch sind die Kosten?</td>
    <td bgcolor=#FFE4b5>
      <?php
      ## Die durchschnittlichen Onlinekosten werden direkt in der Datenbank
      ## über alle Felder berechnet.
      $query = "SELECT AVG(kosten) FROM umfrage";
      $rs    = mysql_query($query, $connection);
      $row   = mysql_fetch_row($rs);
      printf("Im Durchschnitt kostet der Online-Zugang %0.2f &euro; pro Monat.", $row[0]); 
      ?> 
    </td>
  </tr>
  <tr>
    <td bgcolor=#FFE4b5>Wer hat schon mal online gekauft? Und welchen Werte hatte die Bestellung?</td>
    <td bgColor=#FFE4b5>
      <?php
      ## Ermittlung der Anzahl Käufer und der durchschnittliche Wert eines
      ## Kaufs. Die Abfrage wird auf Datensätze eingeschränkt, bei denen
      ## das Feld "bestellt" mit "on" gefüllt ist.
      $query = "SELECT COUNT(*), COUNT(bestellt), AVG(summe) FROM umfrage WHERE bestellt=\"on\"";
      $rs    = mysql_query($query, $connection);
      $row   = mysql_fetch_row($rs);
      if ($row[0] == 0)
      {
        echo 'Niemand hat Online bestellt';
      }
      else
      {
        $bst = sprintf("%0.2f", $row[1] / $row[0] * 100);
        $sum = sprintf("%0.2f", $row[2]);
        echo <<<INFO3
        $bst % der Nutzer haben schon online bestellt. 
        Dabei wurden im Durchschnitt $sum &euro; ausgegeben.
INFO3;
      } 
      ?>
    </td>
  </tr>
  <tr>
    <td valign="top" bgcolor=#FFE4b5>Wie gut fanden Sie unsere Website?</td>
    <td bgColor=#ffe4b5 valign="top">
      <?php
      ## Auswertung der Servicezufriedenheit.
      $query = "SELECT COUNT(service), service, AVG(service) AS average FROM umfrage GROUP BY service";
      $rs    = mysql_query($query, $connection);
      $z1    = $z2 = $z3 = $z4 = $z5 = 0;
      ## Zusätzlich wird hier eine prozentuale Berechnung angeschlossen.
      ## Dazu werden die Werte einzeln ausgewählt (switch) und dann mit
      ## der Summe berechnet. Durch die GROUP BY-Bedingung tritt jede 
      ## Variante nur einmal auf, die Schleife wird also tatsächlich nur
      ## fünfmal durchlaufen.
      while ($row = mysql_fetch_row($rs)) 
      {
        switch ($row[1])
        {
          case 1:
            $z1 = $row[0];
            break;
          case 2:
            $z2 = $row[0];
            break;
          case 3:
            $z3 = $row[0];
            break;
          case 4:
            $z4 = $row[0];
            break;
          case 5:
            $z5 = $row[0];
        }
      }
      ## Nun ist die Anzahl der Wertungen pro Note bekannt, sodass
      ## der prozentuale Anteil und eine Durchschnittsnote berechnet
      ## werden kann.
      $summe = $z1 + $z2 + $z3 + $z4 + $z5;
      $p_z1  = sprintf("%0.2f", $z1 / $summe * 100);
      $p_z2  = sprintf("%0.2f", $z2 / $summe * 100);
      $p_z3  = sprintf("%0.2f", $z3 / $summe * 100);
      $p_z4  = sprintf("%0.2f", $z4 / $summe * 100);              
      $p_z5  = sprintf("%0.2f", $z5 / $summe * 100);       
      $a     = ($z1) + ($z2*2) + ($z3*3) + ($z4*4) + ($z5*5);
      $avg   = sprintf("%0.0f", $a/$summe);
      echo <<<INFO4
      1: $z1 Teilnehmer, entspricht: $p_z1 %<br />
      2: $z2 Teilnehmer, entspricht: $p_z2 %<br />
      3: $z3 Teilnehmer, entspricht: $p_z3 %<br />
      4: $z4 Teilnehmer, entspricht: $p_z4 %<br />
      5: $z5 Teilnehmer, entspricht: $p_z5 %<br />
      <p>Die Durchschnittsnote ist: $avg</p>
INFO4;
      ?>
    </td>
  </tr>
</table>
</div>
</body>
</html>

Hinweise

Beim praktischen Einsatz sollte die Notwendigkeit von Sicherheitsmassnahmen zum Schutz vor Missbrauch bedacht werden. Dazu gehören:

  • Kontrolle einer Mehrfachteilnahme: Verhinderung, dass Nutzer mehrfach an der Umfrage teilnehmen, z. B. durch Sperrung von IP-Adressen und Cookies.
  • Prüfen der Eingabedaten: Prüfung auf sinnvolle Werte und Zusammenhänge zwischen Werten, z. B. durch reguläre Ausdrücke.
  • Erkennung von Manipulationsversuchen: Verhinderung von Manipulationsversuchen durch gefälschte Formulare, z. B. durch Auswertung des Referers.

Beispielsweise kann die Anzeige der Ergebnisse zwingend an eine sinnvolle Eingabe gekoppelt werden, um einen Anreiz zur Teilnahme zu schaffen.