Maetzzen: Problem mit Leerzeichen im name-Attribut

Hallo zusammen,

ich möchte eine Oberfläche erstellen, mit der ich Datensätze aus einer Datenbank auswählen und löschen kann.

Vorgestellt habe ich mir das so:

$sql = "SELECT * FROM fragebogen";
    
    $result = mysqli_query($c, $sql);
    
    $namen = array();
    
    while ($row = mysqli_fetch_array($result)){
    $namen[] = $row['titel'];
    }
    
    echo "<form name='f' method='post' action='Loeschen.php'>";
    foreach ($namen as $i){
    echo "<input type=checkbox name=$i />" .$i ."<br>";
    }
    echo "<input type='submit' name='löschen' value='löschen' /></form>";
    
    
    foreach ($namen as $p){
    if (isset($_POST[$p])){
    
    $delete = "DELETE FROM Fragebogen WHERE titel='$p'";
    mysqli_query($c, $delete);
    echo "<big>$p</big> wurde gelöscht <br>";
    
    }
    }

Die Datensätze werden selektiert und in einem Array gespeichert. Für jeden Datensatz soll eine Checkbox mit Name=Titel generiert werden. Beim submit werden alle gewählten Datensätze gelöscht.

Nun zu meiner Frage:

Das Beispiel funktioniert, jedoch nur wenn der Titel des Fragebogens keine Leerzeichen enthält.

Sind Leerzeichen enthalten, wird der Teil

    if (isset($_POST[$p])){
    
    $delete = "DELETE FROM Fragebogen WHERE titel='$p'";
    mysqli_query($c, $delete);
    echo "<big>$p</big> wurde gelöscht <br>";
    
    }
    }

nicht ausgeführt. Kann es sein, dass das "Name"-Attribut der Checkbox nicht richtig nicht den gewünschten Wert annimmt?

Vielen Dank im Voraus für eure Hilfe!

Gruß Maetzzen

  1. Hi,

    Das Beispiel funktioniert, jedoch nur wenn der Titel des Fragebogens keine Leerzeichen enthält.

    Attributwerte, die Leerzeichen enthalten, müssen in Anführungszeichen stehen.

    nicht ausgeführt. Kann es sein, dass das "Name"-Attribut der Checkbox nicht richtig nicht den gewünschten Wert annimmt?

    Schau Dir halt im Browser im Quelltext an, was dort ankommt …

    cu,
    Andreas a/k/a MudGuard

    1. Hi,

      ich habe gerade den Quelltext angesehen

      Folgendes wird ausgegeben:

      <form name='f' method='post' action='Loeschen.php'>
      <input type='checkbox' name='das ist ein fragebogen' />das ist ein fragebogen<br>
      <input type='checkbox' name='Fragebogen 1' />Fragebogen 1<br>
      <input type='checkbox' name='Fragebogen 41' />Fragebogen 41<br>
      <input type='checkbox' name='Fragebogen 4431' />Fragebogen 4431<br>
      <input type='checkbox' name='Fragebogen 51' />Fragebogen 51<br>
      <input type='checkbox' name='Fragebogen51' />Fragebogen51<br>
      <input type='submit' name='löschen' value='löschen' /></form>
      

      Der Name entspricht also dem Titel des Fragebogens, jedoch kann ich in diesem Beispiel nur den letzten Fragebogen ("Fragebogen51") löschen.

      Kann es sein, dass mein

        $delete = "DELETE FROM Fragebogen WHERE titel='$p'";
      

      nicht stimmt? Das würde mich aber wundern, da

      
      echo "<big>$p</big> wurde gelöscht <br>";
      
      

      dennoch ausgegeben werden müsste.

      PS: Ein Fragebogen besteht aus den Eigenschaften "titel" und "benutzername" (Ersteller).

      Gruß Maetzzen

      1. Tach!

        ich habe gerade den Quelltext angesehen

        Der passt nicht zu deinem im Ausgangsposting gezeigten Code. Hier sind korrekterweise Anführungszeichen gesetzt, in deinem PHP-Code fehlen sie.

        Der Name entspricht also dem Titel des Fragebogens, jedoch kann ich in diesem Beispiel nur den letzten Fragebogen ("Fragebogen51") löschen.

        Mit Anführungszeichen musst du den gesamten Wert bekommen.

        Kann es sein, dass mein

          $delete = "DELETE FROM Fragebogen WHERE titel='$p'";
        

        nicht stimmt?

        Auch das, denn da fehlt die Beachtung des Kontextwechsels.

        Das würde mich aber wundern, da

        echo "<big>$p</big> wurde gelöscht <br>";
        

        dennoch ausgegeben werden müsste.

        Debug-Ausgaben können beim Vergleichen zwischen Wunsch und Wirklichkeit helfen.

        dedlfix.

        1. Hallo Maettzen,

          du hast die Seitenaufbereitung und den Lösch-Code vermischt. Das führt - selbst wenn der DELETE funktioniert - dazu, dass man nach dem ersten Löschen nicht sieht, dass etwas gelöscht wurde. Zumindest musst Du dafür sorgen, dass eine gelöschte Zeile nicht mehr ausgegeben wird. Dafür musst Du Deinen Code umstellen. Wenn $_POST[$p] existierst, musst Du löschen, SONST ausgeben.

          Dass Leerzeichen nicht funktionieren, kann ggf. daran liegen, dass die Maskierung des Leerzeichens in den Post-Daten beim Schreiben ins $_POST Array nicht rückgängig gemacht wird. Der Browser schickt nicht "Fragebogen 1", sondern "Fragebogen+1=on&l%C3%B6schen=l%C3%B6schen".

          Gib mal $p aus, zwischen for und if(isset), und schreibt auch mal einen var_dump vom $_POST.

          Rolf

          --
          Dosen sind silbern
          1. Tach!

            Dass Leerzeichen nicht funktionieren, kann ggf. daran liegen, dass die Maskierung des Leerzeichens in den Post-Daten beim Schreiben ins $_POST Array nicht rückgängig gemacht wird. Der Browser schickt nicht "Fragebogen 1", sondern "Fragebogen+1=on&l%C3%B6schen=l%C3%B6schen".

            Dann wäre PHP kaputt, denn das kümmert sich bereits darum.

            dedlfix.

            1. Hallo dedlfix,

              ok, das wusste ich nicht genau - ich habe noch nie name Attribute mit Space verwendet und hatte kein PHP zum probieren zur Hand.

              Rolf

              --
              Dosen sind silbern
      2. Hallo

        Folgendes wird ausgegeben:

        <form name='f' method='post' action='Loeschen.php'>
        <input type='checkbox' name='das ist ein fragebogen' />das ist ein fragebogen<br>
        <input type='checkbox' name='Fragebogen 1' />Fragebogen 1<br>
        <input type='checkbox' name='Fragebogen 41' />Fragebogen 41<br>
        <input type='checkbox' name='Fragebogen 4431' />Fragebogen 4431<br>
        <input type='checkbox' name='Fragebogen 51' />Fragebogen 51<br>
        <input type='checkbox' name='Fragebogen51' />Fragebogen51<br>
        <input type='submit' name='löschen' value='löschen' /></form>
        

        Der Name entspricht also dem Titel des Fragebogens, jedoch kann ich in diesem Beispiel nur den letzten Fragebogen ("Fragebogen51") löschen.

        Im Attribut „name“ steht der Name des Formularelements, was dazu führt, dass du mehrere POST-Elemente ($_POST['Fragebogen 1'], $_POST['Fragebogen 41'], und so weiter) übermittelt bekommst. Diese haben jedoch keine Werte, die in den Formularelementen jedoch im Attribut „value“ stehen müssten. Dein HTML-Aufbau ist also fehlerhaft.

        Da die Checkboxen offensichtlich eine Gruppe bilden, in der du keinen, einen oder mehrere Werte auswählen kannst, sollten sie alle einen Namen tragen und für die Verarbeitung mit PHP als Array gekennzeichnet sein (z.B. name="frageboegen[]"). Die namen der Fragebögen wechseln in die Value-Attribute, so dass sie im auswertenden PHP-Skript, deinem Beispiel folgend, als $_POST['frageboegen'][0] - $_POST['frageboegen'][4] mit den Fragebogennamen als Werte zur Verfügung stünden. Die Anzahl der Elemente richtet sich nach der Anzahl der ausgewählten Checkboxen. Ist keine ausgewählt, wird auch kein einziges $_POST['frageboegen'] übermittelt.

          $delete = "DELETE FROM Fragebogen WHERE titel='$p'";
        

        Vergiss nicht die kontextgerechte Maskierung. Für den Fall der Verwendung der mysqli-Funktionen wäre das für einen String "… WHERE titel='". mysqli_real_escape_string($connection, $p) ."'".

        Tschö, Auge

        --
        Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
        Toller Dampf voraus von Terry Pratchett
        1. Tach!

          Im Attribut „name“ steht der Name des Formularelements, was dazu führt, dass du mehrere POST-Elemente ($_POST['Fragebogen 1'], $_POST['Fragebogen 41'], und so weiter) übermittelt bekommst. Diese haben jedoch keine Werte, die in den Formularelementen jedoch im Attribut „value“ stehen müssten. Dein HTML-Aufbau ist also fehlerhaft.

          Ohne value wird "on" als Wert genommen. Das ist nicht das Problem.

          dedlfix.

          1. Hallo dedlfix,

            habe jetzt mal live probieren können... (PHP 7.1.8 auf IIS mit fastCGI)

            Die Lösung ist: Das ist ein Legacy-Problem. Bis PHP 5.3 gab es die register_globals Option, und wenn die auf TRUE stand (Default vor PHP 4.2), wurde jeder gepostete Wert zu einer globalen Variablen.

            Variablennamen dürfen weder Punkt noch Space enthalten. Deswegen konvertiert PHP sie in Unterstriche.

            Der Grund für die Konvertierung ist weg. Die Konvertierung nicht. Und ich habe jetzt in php.ini auch nicht spontan einen Schalter gefunden, um das zu ändern.

            So geht's:

                if (isset($_POST[str_replace(' ', '_', $p])) {
                   ...
                }
            

            Rolf

            --
            Dosen sind silbern
            1. Tach!

              Die Lösung ist: Das ist ein Legacy-Problem. Bis PHP 5.3 gab es die register_globals Option, und wenn die auf TRUE stand (Default vor PHP 4.2), wurde jeder gepostete Wert zu einer globalen Variablen.

              Variablennamen dürfen weder Punkt noch Space enthalten. Deswegen konvertiert PHP sie in Unterstriche.

              Trifft aber nur auf Variablennamen zu. Keys von Arrays können alle möglichen Zeichen enthalten. Da konvertiert auch PHP nichts, soweit ich weiß. Eine Ausnahme gibts bei <input type=image>, aber das nimmt man ja kaum.

              Im Zweifelsfall mal mit var_dump($_POST) oder print_r($_POST) schauen, was da wirklich ankommt.

              dedlfix.

              1. Hallo dedlfix,

                Keys von Arrays können alle möglichen Zeichen enthalten.

                Grundsätzlich schon…

                Im Zweifelsfall mal mit var_dump($_POST) oder print_r($_POST) schauen, was da wirklich ankommt.

                Hab ich doch, sonst hätte ich das nicht so geschrieben. Offenbar hat man bei Einführung der Superglobals darauf Wert gelegt, dass die Namen der erzeugten Globals und die Array-Keys identisch sind.

                Edit: Siehe auch hier, erste Note.

                Rolf

                --
                Dosen sind silbern
            2. Vielen Dank Rolf!

              Daran hat es gelegen. Mein Prof konnte mir auch nicht weiterhelfen, da

              ich habe noch nie name Attribute mit Space verwendet

              dies ja eher die Ausnahme darstellt.

              Jetzt habe ich lediglich noch ein Problem, dass ich Datensätze, die mit einem Leerzeichen beginnen, nicht löschen kann. Das versuche ich aber zu vermeiden, indem ich diese beim Erstellen gleich gar nicht zulasse!

              Nochmals danke!

              Gruß Maetzzen

              1. Hallo Maetzzen,

                habe gerade nochmal geguckt - der Browser postet das noch zurück (Namen waren " Bo.x 1" und "Box 2")

                +Bo.x+1=on&Box+2=on&l%C3%B6schen=l%C3%B6schen
                

                aber PHP trimmt es weg. Leerstelle vorneweg - pfui ;-)

                Entweder setzt Du irgendeine Konstante davor_

                echo "<input type=checkbox name='id$i' />" .$i ."<br>";
                

                die du beim Auslesen aus $_POST wieder entfernst, oder du musst solche Namen - wie du sagtest - von vornherein vermeiden.

                Rolf

                --
                Dosen sind silbern
                1. Tach!

                  oder du musst solche Namen - wie du sagtest - von vornherein vermeiden.

                  Besser wäre es, Werte nicht als Namen zu verwenden.

                  <input type="checkbox" name="title[]" value="hier der wert">
                  <input type="checkbox" name="title[]" value="hier ein anderer wert">
                  <input type="checkbox" name="title[]" value="noch besser IDs verwenden, wenn vorhanden">
                  

                  Man bekommt nun aufgrund der [] in $_POST['title'] ein Array, durch das man mit foreach laufen kann.

                  foreach ($_POST['title'] as $title) {
                    var_dump($title);
                  }
                  

                  dedlfix.

                  1. Hallo dedlfix,

                    stimmt, habe Auges diesbezüglichen Hinweis ganz aus selbigen verloren.

                    Rolf

                    --
                    Dosen sind silbern