PHP/Komplexe Formulare

Aus Mikiwiki
< PHP
Wechseln zu: Navigation, Suche

Formulare mit PHP auswerten

Die bisher vorgestellten Beispiel waren vergleichsweise einfach. Es gibt Formularelemente, die mehr als einen Wert zurückgeben können. In HTML ist es grundsätzlich erlaubt, mehrere Elemente mit dem selben Namen zu belegen. Ob gewollt oder nicht, sollten solche Nemnskonflikte in PHP aufgelöst werden können. Eine typische Anwendung sind mehrere Kontrollkästchen in einer Gruppe.

<input type="checkbox" name="skill" value="php">
<input type="checkbox" name="skill" value="asp">
<input type="checkbox" name="skill" value="perl">
<input type="checkbox" name="skill" value="python">

Manchmal sind Mehrfachangaben unbedingt erwünscht und unumgänglich. So kann beispielsweise bei "<select>" mit dem Attribut "multiple" eine Mehrfachauswahl zugelassen werden.

<select name="skill" multiple="multiple" size="3"
  <option value"php">PHP</option>
  <option value="asp">ASP</option>
  <option value="perl">Perl</option>
  <option value="python">Python</option>
</select>

Bei der Auswertung steht diese Auswahl nur in einer einzigen Variable zur Verfügung. Wird die Variable einfach ausgegeben, so wird immer nur der letzte ausgewählte Wert der Liste angezeigt. Es wird also kein Array gebildet und die Auswahl mit "$skill[0]" verweist nicht auf den ersten Eintrag der ausgewählten Elemente; die Zeichenkette wird als Array erfasst und der erste Buchstabe wird ausgegeben.

<?php
if(isset($_POST['skill'])
{
  echo "Sie kennen {$POST['skill']}.";
}
?>

PHP muss deswegen bereits mit dem Namen der Variablen mitgeteilt werden, dass ein Array verwendet werden soll - dazu wird der Name einfach mit eckigen Klammern ("[]") gekennzeichnet; diese haben in HTML keine weitere Bedeutung. PHP nimmt nun an, dass mehr als ein Wert folgt und erzeugt ein Array. Das geschieht natürlich auch dann, wenn in Wirklichkeit nur ein Wert vorliegt. Die Auswertung kann dann mit einer Schleife erfolgen.

<p>Welche Skriptsprachen kennen Sie?</p>
<form action="<?=$_SERVER['PHP_SELF'] ?>" method="post">
  <select name="skill[]" multiple size="4">
    <option value="php">PHP</option>
    <option value="asp">ASP</option>
    <option value="perl">Perl</option>
    <option value="python">Python</option>
  </select>
  <input type="submit" value="Senden" />
</form>
<?php
if (isset($_POST['skill']) && ($skill = $_POST['skill']) > 0)
{
  echo "Sie kennen ";
  for ($i=0;
       ## Ermitteln der Anzahl Formularelemente
       $i < count($_POST['skill']);
       ## Einzeladdressierung der ermittelten Formularelemente und
       ## gleichzeitige Erhähung des Zählers
       print($_POST['skill'][$i++] . " "));
}
?>

Formulare mit PHP erzeugen

Bisher wurden die Werte stets fest in die Formulare eingebaut. Die Vorgaben für die Auswahl können auch dynamisch erzeugt werden. Da hier noch keine Datenbanken verwendet werden, werden die Werte zuerst in Variablen erfasst und dann wieder ausgelesen. Bei der Verwendung assoziativer Arrays können die Indizes als Werte für die "<option>"-Tags eingesetzt und der zugeordnete Wert für die Anzeige verwendet werden.

<p>Welche Skriptsprachen kennen Sie?</p>
<form action="<?=$_SERVER['PHP_SELF']?>" method="post">
<?php
$skill[] = "PHP";
$skill[] = "ASP";
$skill[] = "Perl";
$skill[] = "Python";
## Abstimmung der Listenanzeige auf die Anzahl darzustellender Elemente
echo "<select name=\"skill[]\" multiple=\"multiple\" size=\"" . count($skill) . "\">\n";
for ($i = 0; $i < count($skill); $i++) 
{
  echo "  <option value=\"" . $skill[$i] . "\" />" . $skill[$i] . "\n";
}
?>
  </select>
  <input type="submit" value="Senden" />
</form>
<?php
if (isset($_POST['skill']) && ($skill = $_POST['skill']) > 0) 
{
  echo "Sie kennen ";
  for ($i = 0; $i < count($skill); print($skill[$i++]));
  $skill="";     ## Zum Test diese Zeile entfernen!
}
?>

Sticky Forms: Den Zustand eines Formulars erhalten

Bei der Anzeige kann es sinnvoll sein, den aktuellen Zustand einer Auswahl zu behalten. Bei der Anzeig des letzten Beispiels fällt auf, dass die durch Mausklick erfolgten Markierungen beim erneuten Senden des Formulars wieder verschwinden. Das "<option>"-Tag kennt das Attribut "selected", um eine Markierung zu setzen. Die aktivierte Option müsste also durch dynamisches Erzeugen dieses Attributs gekennzeichnet werden. Beim Umsetzen fällt auf, dass mehr auf die Belange von Arrays Rücksicht genommen werden muss, als auf die Formularauswertung.

<?php
## Definition
$sskill = array("ph" => "PHP", 
                "ap" => "Active Server Pages",
                "pl" => "Perl",
                "pt" => "Python");
?>
<form action="<?=$_SERVER['PHP_SELF']?>" method="post">
<p>Welche Skriptsprachen kennen Sie?</p>
<?php
echo "<select name=\"skill[]\" multiple=\"multiple\" size=\"" . (count($sskill)+1) . "\">";
echo "  <option value=\"\">Keine</option>";
## Auslesen und Ausgeben des assoziativen Arrays mit "while" ("foreach" wäre auch möglich),
## mangels Indizes nicht mir "for".
while (list($key, $val) = each($sskill))
{
  echo "<option value=\"" . $key . "\"";
  ## Prüfung gegen das aus den Formularelementen ausgelesene Array "$skill". Die Prüfung
  ## mit "isset" wird benötigt, falls das Formular ohne Auswahl abgeschickt wird.
  if (isset($_POST['skill']) && in_array($key, $_POST['skill']))
  {
    ## Bei Übereinstimmung wird das Attribut "selected" ausgegeben
    echo " selected=\"selected\"";
  }
  echo ">" . $val . "</option>\n";
}
?>
  </select>
  <input type="submit" value="Senden" />
</form>
<?php
## Ausgabe
if (isset($_POST['skill']) && ($skill = $_POST['skill']) > 0)
{
  echo "Sie kennen:<br />";
  while (list($key, $val) = each($_POST['skill']))
  {   
    if ($val == "")
    {
      echo "Keine Skriptsprachen";
      break;
    }
    echo "$sskill[$val] ($val)<br />";
  }     
}
?>

Bei anderen Elementen ist der Erhalt etwas einfacher. Zur Verminderung der Tipparbeit empfiehlt sich folgendes Vorgehen:

  • Abrufen aller Feldwerte
  • Prüfung der Werte auf sinnvollen Inhalt
  • Speichern der Werte in einfachen Variablen
  • Einbau der Variablen in das Formular

Dazu ein Beispiel. Bei Kontrollkästchen und Optionsfeldern sollte an die Attribute "checked" bzw. "selected" gedacht werden.

<?php
$name = isset($_POST['Feldname']) ? $_POST['Feldname'] : "";
echo <<<FORM
  <input type="text" name="Feldname" value="<?php echo $name; ?>" />
FORM;
?>

Statt "isset" kann auch der folgende Ausdruck verwendet werden.

if (array_key_exists('name', $_POST))
{
  ## Code, wenn in Ordnung
}

Zum Prüfen, ob ein Formularelement, das eine Mehrfachauswahl zulässt, tatsächlich mit mehreren Elementen gefüllt ist, geht folgendes.

$werte = $_POST['name'];
if (is_array($werte))
{
  ## Code, wenn in Ordnung
}

Globale Formularvariablen

Um zu ermitteln, wie die einzelnen Felder heissen, kann auf alle übermittelten Formularvariablen zugegriffen werden. "$_POST" ist ein assoziatives Array, das als Indizes die Namen aller Formularelemente und als Werte deren Inhalte enthält.

<?php
if (isset($_POST['sent']))
{
  echo "<p>Sie haben folgende Daten gesendet:</p>\n";
  while (list($key, $val) = each($_POST))
  {
      echo "<B>$key</B>: $val<BR>\n";
  }
  echo <<<SENDFORM
  <form method="post" action="{$_SERVER['PHP_SELF']}">
    <input type="submit" value="Neue Nachricht senden?">
  </form>
SENDFORM;
} 
else 
{
?>
<h3>Wie hat Ihnen das Buch bisher gefallen?</h3>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<table>
  <tr>
    <td>Mein Name:</td>
    <td><input type="text" name="name" size="50" /></td>
  </tr>
  <tr>
    <td>Meine E-Mail:</td>
    <td><input type="text" name="email" size="50" /></td>
  </tr>
  <tr>
    <td>Bewertung:</td>
    <td>1<input type="radio" name="rank" value="1" />
        2<input type="radio" name="rank" value="2" checked="checked" />
        3<input type="radio" name="rank" value="3" />
        4<input type="radio" name="rank" value="4" />
        5<input type="radio" name="rank" value="5" />
        (Schulnoten)
    </td>
  </tr>
  <tr>
    <td valign="top">Nachricht:</td>
    <td>
      <textarea cols="30" rows="6" name="message">Ihre Nachricht...</textarea>
    </td>
  </tr>
  <tr>
    <td>Wo haben Sie es gekauft?</td>
    <td><select size="1" name="purchase">
	  <option value="Fachbuchhandel">Fachbuchhandel</option>
	  <option value="Kaufhaus">Kaufhaus</option>
	  <option value="Online">Online</option>
	  <option value="Verlag">Verlag</option>
	  <option value="Nur geliehen" >Nur geliehen</option>
	</select>
    </td>
  </tr>
  <tr>
    <td colspan="2"><input type="submit" value="Absenden" />
                    <input type="reset" />
                    <input type="hidden" name="sent" value="1" /> 
    </td>
  </tr>
</table>
</form>
<?php
}
?>

Da PHP 5 keine automatische Registrierung der Formularvariablen mehr vornimmt, ist die Benennung der Variablen recht unkritisch geworden. Trotzdem sollten eindeutige Namen für die Felder vergeben und keine gleichnamigen Variablen eingesetzt werden.

Im Zusammenhang mit dem Tag "<textarea>" können Probleme auftreten, wenn der eingegebene Text anderweitig zur Anzeige gebracht werden soll. Zeilenumbrüche innerhalb des erfassten Textes entsprechen dem ASCII-Standard und werden in PHP mit dem Code "\n" dargestellt. Um die Darstellung nicht zu verfälschen, wäre in HTML aber eine Ausgabe mit "<br />" erwünscht. Dafür kann eine einfache Textersetzung oder die ausdrücklich dafür entworfene Funktion "nl2br" verwendet werden.

<?php
if (isset($_POST['sent']) 
  && 
  isset($_POST['name'])
  &&
  isset($_POST['message'])
  &&
  isset($_POST['email'])
  &&
  isset($_POST['rank'])
  &&
  isset($_POST['purchase']))
{   
  $message = nl2br($_POST['message']);
  echo <<<FORMANSWER
  Sie haben folgende Nachricht gesendet:<p />
  <b>Ihr Name:</b> {$_POST['name']}<br />
  <b>E-Mail:</b> {$_POST['email']}<br />
  <b>Bewertung:</b> {$_POST['rank']}<br />
  <b>Ihre Nachricht:</b><br />
  <div style="background-color:#DDDDDD">$message</div>
  <b>Gekauft bei: </b>{$_POST['purchase']}
  <form method="post" action="{$_SERVER['PHP_SELF']}">
  <input type="submit" value="Neue Nachricht senden?" />
  </form>
FORMANSWER;
}
else
{
?><h3>Wie hat Ihnen das Buch bisher gefallen?</h3>
<form method="post" action="<?=$_SERVER['PHP_SELF']?>">
<table>
  <tr>
    <td>Mein Name:</td>
    <td><input type="text" name="name" size="50" /></td>
  </tr>
  <tr>
    <td>Meine E-Mail:</td>
    <td><input type="text" name="email" size="50" /></td>
  </tr>
  <tr>
    <td>Bewertung:</td>
    <td>
        1<input type="radio" name="rank" value="1" />
        2<input type="radio" name="rank" value="2" checked="checked" />
        3<input type="radio" name="rank" value="3" />
        4<input type="radio" name="rank" value="4" />
        5<input type="radio" name="rank" value="5" />
        (Schulnoten)
    </td>
  </tr>
  <tr>
    <td valign="top">Nachricht:</td>
    <td>
      <textarea cols="30" rows="6" name="message">Ihre Nachricht...</textarea>
    </td>
  </tr>
  <tr>
    <td>Wo haben Sie es gekauft?</td>
    <td>
      <select size="1" name="purchase">
        <option value="Fachbuchhandel" >Fachbuchhandel</option>
        <option value="Kaufhaus" >Kaufhaus</option>
        <option value="Online" >Online</option>
        <option value="Verlag" >Verlag</option>
        <option value="Nur geliehen" >Nur geliehen</option>
      </select>
    </td>
  </tr>
  <tr>
    <td colspan="2">
      <input type="submit" value="Absenden" />
      <input type="reset" />
      <input type="hidden" name="sent" value="1" /> 
    </td>
  </tr>
 </table>
</form>
<?php
}
?>