Seite bei Formular mit "post" nicht neu laden mit XMLHttpRequest


Dragosius

Erfahrenes Mitglied
Hallo zusammen,

ich habe momentan folgendes Formular:
HTML:
    <form action="<?php echo filter_input(INPUT_SERVER, 'REQUEST_URI'); ?>" method="post">
        <input type="text" name="shout" style="width:98%" maxlength="200"><br />
        <input type="submit" name="butshout" value="Senden">
    </form>

Dies wird folgendermaßen ausgewertet:
PHP:
    // Neuer Eintrag in die Shoutbox
    $shoutEintrag = filter_input(INPUT_POST, 'shout', FILTER_SANITIZE_STRING);
    if( !empty(filter_input(INPUT_POST, 'butshout', FILTER_SANITIZE_STRING)) && !empty($shoutEintrag) ) {
        $alteEintraege = mysqli_fetch_assoc(sqlQuery("SELECT `text` FROM `shoutbox` WHERE `user_id`='".$userId."' ORDER BY `id` DESC LIMIT 0,1"));
        if( $alteEintraege['text'] != $shoutEintrag ) { // Überprüfung, ob der gleiche Inhalt bereits abgesendet wurde
            sqlQuery("INSERT INTO `shoutbox` (`text`,`datum`,`user_id`) VALUES ('".mysqli_real_escape_string($db_link, $shoutEintrag)."',NOW(),'$userId')");
        }
    }

Es handelt sich hierbei um eine Shoutbox.
Wie kann ich es denn (mit XMLHttpRequest) lösen, dass nach dem Absenden die Webseite nicht neu geladen wird?

Des Weiteren würde ich es gerne noch so realisieren, dass gleichzeitig der Inhalt der Shoutbox neu geladen wird, damit man seinen Eintrag sofort sieht.
Ich habe bereits eine Funktion, welche mir die Shoutbox regelmäßig neu lädt:
Javascript:
setInterval(function() {
    hole_shoutbox();
},10000);

Kann mir da jemand weiterhelfen?


Vielen Dank
 

Sempervivum

Erfahrenes Mitglied
Warum willst Du es denn mit XMLHttpRequest lösen, in deinem anderen Thread benutzt Du doch $.ajax, das wäre wesentlich einfacher und übersichtlicher zu handhaben?
 

Sempervivum

Erfahrenes Mitglied
Ich würde dabei so vorgehen: Die Datei shoutbox.php hast Du ja schon. Beim Ajax-Aufruf dieser Datei würde ich den Text als POST-Parameter mitgeben, wobei dieser Parameter optional wäre. Das PHP würde dann den neuen Text in die DB eintragen, wenn der Parameter vorhanden ist und in jedem Fall die Inhalte auslesen, wie Du es schon hast, und zurück liefern. Dann kannst du die Datei für beides einsetzen: Posten eines Textes mit Parameter und zyklisches Holen der Inhalte mit setIntverval().
 

Dragosius

Erfahrenes Mitglied
Ok theoretisch habe ich es nun glaube ich verstanden, aber könntest du mir eventuell noch helfen, wie ich das am Besten umsetzen kann?
 

Sempervivum

Erfahrenes Mitglied
OK, wenn Du das PHP-Skript mit Ajax aufrufst, brauchst Du dieses butshout nicht mehr. Sonst kannst Du alles so beibehalten und fügst am Ende das Auslesen der Einträge hinzu, genau so wie Du es schon hast:
PHP:
    // Neuer Eintrag in die Shoutbox
    $shoutEintrag = filter_input(INPUT_POST, 'shout', FILTER_SANITIZE_STRING);
    if( /*!empty(filter_input(INPUT_POST, 'butshout', FILTER_SANITIZE_STRING)) &&*/ !empty($shoutEintrag) ) {
        $alteEintraege = mysqli_fetch_assoc(sqlQuery("SELECT `text` FROM `shoutbox` WHERE `user_id`='".$userId."' ORDER BY `id` DESC LIMIT 0,1"));
        if( $alteEintraege['text'] != $shoutEintrag ) { // Überprüfung, ob der gleiche Inhalt bereits abgesendet wurde
            sqlQuery("INSERT INTO `shoutbox` (`text`,`datum`,`user_id`) VALUES ('".mysqli_real_escape_string($db_link, $shoutEintrag)."',NOW(),'$userId')");
        }
    }
    // hier das Auslesen der Eintraege hinzu fuegen, so wie Du es schon hast.

Dann statt des Submit type="button" verwenden und darauf einen Eventlistener registrieren, der beim Klick den Text abschickt:
Code:
        <input type="text" id="shout" style="width:98%" maxlength="200"><br />
        <input type="button" id="butshout" value="Senden">
<script>
    function doShout(txt) {
          // Daten vorbereiten: Nur wenn ein Text vorhanden ist, diesen eintragen,
          // andernfalls bleibt das Objekt leer
          if (txt) let data = {shout: txt};
          else let data = {};
          $.ajax({
            type: 'POST',
url: 'shoutpox.php',
data: data, // Daten uebergeben
success: function(data1){
$('#shoutbox').html(data1);
}
         });
   }

    $('#butshout').on('click', (event) => {
        const txt = $('#shout').text();
        doShout(txt);
    });
    setInterVal(doShout, 5000);
</script>
(irgend wie zerstört das Forum die Einrückungen)
ungetestet
 

Dragosius

Erfahrenes Mitglied
Das funktioniert leider noch nicht.
Warum genau muss ich denn bei der URL shoutbox.php angeben?
Das ist doch nur die Datei, welche die Einträge anzeigt.

Einbindung im Template der Shoutbox:
HTML:
<div style="width:100%;" id="box">
    <div style="width:100%;" id="shoutbox">
    </div>
 
    <input type="text" id="shout" style="width:98%" maxlength="200"><br />
    <input type="button" id="butshout" value="Senden">&nbsp;<a href="index.php?info=shoutbox-archiv">[Archiv]</a>
    <script>
    function doShout(txt) {
        // Daten vorbereiten: Nur wenn ein Text vorhanden ist, diesen eintragen,
        // andernfalls bleibt das Objekt leer
        if (txt) let data = {shout: txt};
        else let data = {};
        $.ajax({
            type: 'POST',
            url: 'index.php',
            data: data, // Daten uebergeben
            success: function(data1){
                $('#shoutbox').html(data1);
            }
        });
    }

    $('#butshout').on('click', (event) => {
        const txt = $('#shout').text();
        doShout(txt);
    });
    setInterVal(doShout, 5000);
</script>
</div>

Auswertung in der index.php, wo das Template von der Shoutbox eingebunden ist:
PHP:
    // Neuer Eintrag in die Shoutbox
    $shoutEintrag = filter_input(INPUT_POST, 'shout', FILTER_SANITIZE_STRING);
    if( /*!empty(filter_input(INPUT_POST, 'butshout', FILTER_SANITIZE_STRING)) &&*/ !empty($shoutEintrag) ) {
        $alteEintraege = mysqli_fetch_assoc(sqlQuery("SELECT `text` FROM `shoutbox` WHERE `user_id`='".$userId."' ORDER BY `id` DESC LIMIT 0,1"));
        if( $alteEintraege['text'] != $shoutEintrag ) { // Überprüfung, ob der gleiche Inhalt bereits abgesendet wurde
            sqlQuery("INSERT INTO `shoutbox` (`text`,`datum`,`user_id`) VALUES ('".mysqli_real_escape_string($db_link, $shoutEintrag)."',NOW(),'$userId')");
            hole_shoutbox();
        }
    }


Aktuell wird die Nachricht noch nicht in der Datenbank gespeichert, also noch nicht abgesendet.
 
Zuletzt bearbeitet:

Sempervivum

Erfahrenes Mitglied
Warum genau muss ich denn bei der URL shoutbox.php angeben?
Das ist doch nur die Datei, welche die Einträge anzeigt.
Musst Du nicht aber das ist meine Empfehlung: Eine einzige Datei verwenden, die sowohl den Eintrag erledigt als auch das Auslesen der Einträge.
Möglicher Weise hat deine PHP-Datei für das Eintragen aber einen anderen Namen, dann musst Du den nehmen.

In deinem PHP sehe ich das hole_shoutbox() - wenn Du damit die Javascript-Datei meinst, kann das nicht funktionieren. Du musst das PHP, das Du in dem anderen Thread hast für das Auslesen und echo der Tabelle dort hin kopieren.

Allerdings wenn shoutbox.php die Einträge anzeigt, kannst Du auf Kopieren verzichten und statt dessen die Datei inkludieren:
Code:
    // Neuer Eintrag in die Shoutbox
    $shoutEintrag = filter_input(INPUT_POST, 'shout', FILTER_SANITIZE_STRING);
    if( /*!empty(filter_input(INPUT_POST, 'butshout', FILTER_SANITIZE_STRING)) &&*/ !empty($shoutEintrag) ) {
        $alteEintraege = mysqli_fetch_assoc(sqlQuery("SELECT `text` FROM `shoutbox` WHERE `user_id`='".$userId."' ORDER BY `id` DESC LIMIT 0,1"));
        if( $alteEintraege['text'] != $shoutEintrag ) { // Überprüfung, ob der gleiche Inhalt bereits abgesendet wurde
            sqlQuery("INSERT INTO `shoutbox` (`text`,`datum`,`user_id`) VALUES ('".mysqli_real_escape_string($db_link, $shoutEintrag)."',NOW(),'$userId')");
            hole_shoutbox();
        }
    }
    // Shoutbox lesen und in einer HTML-Tabelle ausgeben
    include 'shoutbox.php';
 
Zuletzt bearbeitet:

Dragosius

Erfahrenes Mitglied
Danke für den Tipp, nur das ist ja schon ein Fehler weiter, da ich aktuell ja noch nicht Mal zum INSERT-Statement komme.
Aktuell werden die neuen Einträge noch nicht in die Datenbank geschrieben und ich habe um ehrlich zu sein keine Ahnung, woran das liegt.
 

Sempervivum

Erfahrenes Mitglied
Wenn etwas nicht funktioniert und man nicht weiß warum, muss man ins Debugging einsteigen. Als erstes die Console beobachten, ob Fehlermeldungen kommen. Im PHP-Skript dieses an den Anfang schreiben:
Code:
ini_set('display_errors', '1');
error_reporting(E_ALL);
dann werden Fehlermeldungen ausgegeben. Diese werden ja über Ajax zurück geliefert und auf der HTML-Seite angezeigt.
Daraus sollten sich Hinweise ergeben wo der Fehler liegt.
 
Zuletzt bearbeitet:

basti1012

Erfahrenes Mitglied
Danach könntest du vieleicht auch noch schaun was im $_POST steht
PHP:
ini_set('display_errors', '1');
error_reporting(E_ALL);
echo "<pre>";
print_r($_POST);// oder $_GET
echo "</pre>";
 

Dragosius

Erfahrenes Mitglied
Es wird nichts angezeigt.
Der Text im input-Feld wird erst gar nicht abgeschickt.
Der Code ist oben zu sehen, da muss vermutlich noch ein Fehler drinnen sein?
 

Dragosius

Erfahrenes Mitglied
Ich bin bei JavaScript mit den events und so noch nicht wirklich fit.
Könntest du mir da etwas auf die Sprünge helfen? :)
 

Sempervivum

Erfahrenes Mitglied
Gern. Hier habe ich einige Fehler beseitigt:
Code:
    <script>
        function doShout(txt) {
            // Daten vorbereiten: Nur wenn ein Text vorhanden ist, diesen eintragen,
            // andernfalls bleibt das Objekt leer
            // data muss zuvor definiert werden.
            let data;
            if (txt) data = { shout: txt };
            else data = {};
            $.ajax({
                type: 'POST',
                url: 'index.php',
                data: data, // Daten uebergeben
                success: function (data1) {
                    $('#shoutbox').html(data1);
                }
            });
        }

        $('#butshout').on('click', (event) => {
            // Da es ein Input ist, muss man den Inhalt mit val() lesen
            const txt = $('#shout').val();
            doShout(txt);
        });
        // Hier war ein Schreibfehler bei setInterVal
        setInterval(doShout, 5000);
    </script>
Außerdem war das a-Tag nicht abgeschlossen.
 

Dragosius

Erfahrenes Mitglied
Irgendwie wird jetzt ständig die Seite neu geladen, obwohl ich nichts machen? :unsure:

Liegt das eventuell daran, dass "setInterval(doShout, 5000);" außerhalb der Funktion steht?
Wofür wird das denn an dieser Stelle eigentlich benötigt?

Momentan kann ich gerade nicht testen, da ich nun 504 Gateway Time-out bekomme.
Ich vermute, das war nun zu häufiges neu laden.

Nachtrag:
Es liegt an dieser Zeile.
Ich habe sie auskommentiert und mir wird die Seite nicht mehr ständig neu geladen.
 
Zuletzt bearbeitet:

Dragosius

Erfahrenes Mitglied
Es funktioniert aber auch ohne das "setInterval(doShout, 5000);" sehr gut.
Da wird der Bereich auch zeitnah neu geladen.

Jetzt hätte noch noch 2 Fragen:

1.
Wie kann ich denn das input-Feld leeren, nachdem ich auf den Absenden-Button geklickt habe?
Aktuell bleibt der abgesendete Text noch drinnen stehen.

2.
Funktioniert das ganze auch ohne den Absenden-Button, indem man einfach Enter drückt. (Am Besten zusätzlich, also dass der Absenden-Button auch noch funktioniert.)
 
Zuletzt bearbeitet:

Sempervivum

Erfahrenes Mitglied
Liegt das eventuell daran, dass "setInterval(doShout, 5000);" außerhalb der Funktion steht?
Wofür wird das denn an dieser Stelle eigentlich benötigt?
Ich denke, damit man auch zu sehen bekommt, was andere Benutzer schreiben. Siehe deinen anderen Thread.

Wie kann ich denn das input-Feld leeren, nachdem ich auf den Absenden-Button geklickt habe?
Aktuell bleibt der abgesendete Text noch drinnen stehen.
Das kannst Du im success-Callback tun:
Code:
            $.ajax({
                type: 'POST',
                url: 'index.php',
                data: data, // Daten uebergeben
                success: function (data1) {
                    $('#shoutbox').html(data1);                
                    $('#shout').val('');
                }
            });
 

Dragosius

Erfahrenes Mitglied
Ich glaube, ich habe durch die Shoutbox-Verbesserungen nun einige Fehler eingebaut.

Diese Fehlermeldung bekomme ich nun ständig in der Konsole:
1594932065737.png
 

Sempervivum

Erfahrenes Mitglied
In welcher Zeile tritt denn der Fehler auf? Klicke mal auf die rote Fehlermeldung, dann müsste er zu der betr. Zeile gehen.
 
Zuletzt bearbeitet: