{"id":1461,"date":"2018-09-29T11:34:25","date_gmt":"2018-09-29T09:34:25","guid":{"rendered":"http:\/\/evileu.de\/zum-schwarzen-pinguin\/?p=1461"},"modified":"2018-11-10T10:35:43","modified_gmt":"2018-11-10T09:35:43","slug":"ein-kleiner-chat-in-php-wieder-mal-was-fuer-minimalisten","status":"publish","type":"post","link":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/2018\/09\/29\/ein-kleiner-chat-in-php-wieder-mal-was-fuer-minimalisten\/","title":{"rendered":"Ein kleiner Chat in PHP &#8211; wieder mal was f\u00fcr Minimalisten"},"content":{"rendered":"<p>Da ich mich derzeit viel im Chat in meinem Lieblings-Handarbeitsforum herumtreibe, dachte ich mir: so einen kleinen, eher spartanischen Chatroom solltest du eigentlich auch selber programmieren k\u00f6nnen, das kann so schwierig nicht sein. Bei Google gibt es -zig Beispiele, wie man so etwas angehen k\u00f6nnte, ich hab mich auf die Suche nach etwas Einfachem gemacht und bin hier bei <a href=\"https:\/\/www.php-einfach.de\/experte\/codeschnipsel\/10207-php-chat-mit-ajax\/\">php-einfach.de<\/a> f\u00fcndig geworden.<\/p>\n<p>Ich hab allerdings ein paar Fehler bereinigt, auf PHP 7 umgeschrieben, die Ajax-Funktionalit\u00e4t eliminiert (warum kompliziert wenns auch einfach geht?), die MySQL-Tabelle komplett anders strukturiert, eine Teilnehmerliste hinzugef\u00fcgt und s\u00e4mtliche Formatierungen umgekrempelt, so dass letztendlich eine komplett umgeschmissene Logik dabei herausgekommen ist. Wie gesagt, die Grundidee stammt von php-einfach.de, und ich bedanke mich auch artig f\u00fcr den Denkansto\u00df. Aber ich denke, es ist genug kreative Eigenleistung dazugekommen, dass ich den Source hier als auf meinem Mist gewachsen einstellen kann.<\/p>\n<h2>Die Voraussetzungen<\/h2>\n<p>Viel ist nicht dran: man soll seinen Nick und seine Nachricht eingeben k\u00f6nnen, auf den Senden!-Button klicken, und dann soll im Chatfenster die Nachricht f\u00fcr alle sichtbar am unteren Ende des Fensters auftauchen. Ich hab noch die Uhrzeit wann die Nachricht geschrieben wurde mit dazugenommen, und protokolliere im Hintergrund auch das Datum mit, da ich in meinem Chat immer nur die Beitr\u00e4ge des heutigen Tages anzeigen m\u00f6chte.<\/p>\n<p>Aussehen tut das Ganze so:<\/p>\n<div id=\"attachment_1463\" style=\"width: 1263px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-1463\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-1463\" src=\"http:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat.jpg\" alt=\"screenshot_chat\" width=\"1253\" height=\"612\" srcset=\"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat.jpg 1253w, https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat-300x147.jpg 300w, https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat-768x375.jpg 768w, https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat-1024x500.jpg 1024w, https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/screenshot_chat-624x305.jpg 624w\" sizes=\"(max-width: 1253px) 100vw, 1253px\" \/><p id=\"caption-attachment-1463\" class=\"wp-caption-text\">screenshot_chat<\/p><\/div>\n<p>Man kann seinen Nick eingeben (der bleibt auch nach dem Abschicken stehen), man kann seine Nachricht eingeben, und man kann auf den Senden!-Button klicken. Im Chatfenster scrollen die \u00e4lteren Eintr\u00e4ge nach oben weg, der neueste Eintrag landet immer ganz unten, und es wird noch die Uhrzeit zu jedem Beitrag angezeigt. Es werden nur die Eintr\u00e4ge des heutigen Tages angezeigt, den Rest habe ich nat\u00fcrlich auch gebunkert, daraus k\u00f6nnte man noch ein Chat-Archiv erstellen. Rechts kriegt man noch eine Liste angezeigt, wer heute schon aller im Chat war, und das wars.<\/p>\n<h2>Im Hintergrund: nat\u00fcrlich eine MySQL-Tabelle<\/h2>\n<p>Die ist recht einfach strukturiert und hei\u00dft bei mir chat_daten:<\/p>\n<div id=\"attachment_1465\" style=\"width: 523px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-1465\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-1465\" src=\"http:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/chat_daten-1.jpg\" alt=\"chat_daten\" width=\"513\" height=\"240\" srcset=\"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/chat_daten-1.jpg 513w, https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-content\/uploads\/2018\/09\/chat_daten-1-300x140.jpg 300w\" sizes=\"(max-width: 513px) 100vw, 513px\" \/><p id=\"caption-attachment-1465\" class=\"wp-caption-text\">chat_daten<\/p><\/div>\n<p>Eine AutoIncrement-id als Prim\u00e4rschl\u00fcssel, und vier Textfelder f\u00fcr nick, eintrag, uhrzeit und datum, das war schon alles.<\/p>\n<h2>Der Sourcecode<\/h2>\n<p>Wir packen die Connect-Daten in eine externe Datei:<\/p>\n<pre>&lt;?php \r\n$server\u00a0\u00a0\u00a0 = 'localhost'; \r\n$user\u00a0\u00a0\u00a0 = 'root'; \r\n$pass\u00a0\u00a0\u00a0 = ''; \r\n$db\u00a0\u00a0\u00a0 = 'chat'; \r\n$table\u00a0\u00a0\u00a0 = 'chat_daten'; \r\n$conn=mysqli_connect($server, $user,$pass); \r\nmysqli_select_db($conn,$db); \r\n?&gt;<\/pre>\n<p>Die Felder f\u00fcr Nick und Eintrag und den Senden-Button packen wir in ein Formular:<\/p>\n<pre>&lt;?php \u00a0\r\n\/\/Config auslesen \r\nrequire_once('inc\/config.php'); \r\n\u00a0 \r\n$heute = date(\"d.m.Y\",time());\r\necho '&lt;img src=\"el_logo.jpg\"&gt;';\r\necho '&lt;h1&gt;Evis Chat live am '.$heute.'&lt;\/h1&gt;';\r\n\r\necho ' \r\n\u00a0&lt;form action=\"index.php\" method=\"post\"&gt; \r\n\u00a0\u00a0\u00a0 &lt;table border=\"0\"&gt; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;tr&gt; ';\r\n<span style=\"color: #008000;\">\/\/Falls ein Nick eingegeben wurde, diesen als default in die Textbox setzen<\/span>\r\n<span style=\"color: #008000;\">if(!empty($_POST['nick'])){<\/span>\r\n<span style=\"color: #008000;\">\u00a0\u00a0 \u00a0$akt_nick = $_POST['nick'];<\/span>\r\n<span style=\"color: #008000;\">}<\/span>\r\n<span style=\"color: #008000;\">else{<\/span>\r\n<span style=\"color: #008000;\">\u00a0\u00a0 \u00a0$akt_nick='';<\/span>\r\n<span style=\"color: #008000;\">};<\/span>\r\n\u00a0\u00a0 \u00a0\r\necho '&lt;th&gt;Nickname:&lt;\/th&gt;&lt;td&gt;&lt;input type=\"text\" name=\"nick\" value=\"'.$akt_nick.'\" id=\"textbox1\"&gt;&lt;\/td&gt;&lt;\/tr&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;tr&gt; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;th&gt;Nachricht:&lt;\/th&gt;&lt;td&gt;&lt;input type=\"text\" name=\"eintrag\" value=\"\" id=\"textbox\"&gt;&amp;nbsp;&lt;input type=\"submit\" name=\"eintragen\" value=\"Senden!\" id=\"button\"&gt;&amp;nbsp;&lt;\/td&gt; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/tr&gt; \r\n\u00a0\u00a0\u00a0 &lt;\/table&gt; ';\r\n<\/pre>\n<p>Damit man den Nick nicht immer neu eingeben muss, frage ich ab ob das Feld schon gesetzt wurde und schreibe dann den Wert als Default rein.<\/p>\n<p>Dann starte ich, wenn auf den Button Senden geklickt wurde, und schreibe mir Nick, Eintrag, Datum und Uhrzeit in die Datenbank:<\/p>\n<pre>if(isset($_POST['eintragen'])){ \r\n\r\nif(empty($_POST['nick']) or empty($_POST['eintrag'])){ \r\n\u00a0\u00a0\u00a0 echo '&lt;script&gt;alert(\"Bitte Nick UND Message eingeben\")&lt;\/script&gt;'; \r\n}else{ \r\n\u00a0\u00a0\u00a0 \/\/Variablen definieren und mit \"POST\" Daten f\u00fcllen (Mit htmlspecialchars filtern, Apostrophe maskieren..) \r\n\u00a0\u00a0\u00a0 $nick = addslashes(htmlspecialchars($_POST['nick'])); \r\n\u00a0\u00a0\u00a0 $eintrag = addslashes(htmlspecialchars($_POST['eintrag'])); \r\n\u00a0\u00a0 \u00a0$uhrzeit = date(\"H:i\",time());\r\n\u00a0\u00a0 \u00a0$datum = date(\"d.m.Y\",time());\r\n\r\n\u00a0\u00a0 \u00a0\r\n\/\/Nick + Eintrag + datum+uhrzeit in die Datenbank schreiben \r\n\u00a0\u00a0\u00a0 mysqli_query($conn,\"INSERT INTO $table \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (nick,eintrag,uhrzeit, datum) VALUES \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ('$nick', '$eintrag', '$uhrzeit', '$datum')\"); \r\n\u00a0\u00a0\u00a0 } \r\n\r\n}<\/pre>\n<p>Falls kein Nick oder keine Nachricht eingegeben wurden, gibts einen Alert, andernfalls mache ich den Insert mit den aktuellen Daten.<\/p>\n<p>F\u00fcr die Ausgabe des Chats baue ich mir eine Div mit zwei darin enthaltenen Divs, weil ich Nick und Nachricht linksb\u00fcndig, die Uhrzeit aber rechtsb\u00fcndig ausgeben m\u00f6chte. Das CSS dazu gibt es weiter unten, hier erstmal die Divs f\u00fcr das Chatfenster:<\/p>\n<pre>\/\/alle Eintr\u00e4ge von heute ausgeben\r\necho '&lt;div id=\"chat_fenster\" &gt;';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Nur die Eintr\u00e4ge von heute auslesen\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $abfrage = mysqli_query($conn,\"SELECT * FROM $table WHERE datum LIKE '$datum'\"); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while($row = mysqli_fetch_array($abfrage,MYSQLI_ASSOC)) \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo '&lt;div id =\"nick_und_message\"&gt;&lt;span style=\"color:red\"&gt;'.$row['nick'].':&lt;\/span&gt;&lt;span style =\"color:black\"&gt;'.$row['eintrag'].'&lt;\/span&gt;&lt;\/div&gt;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0&lt;div id = \"uhrzeit\"&gt;&lt;span style =\"color:green\"&gt;'.$row['uhrzeit'].'&lt;\/span&gt;&lt;\/div&gt;&lt;br&gt;'; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\necho '&lt;\/div&gt;';<\/pre>\n<p>Als kleines Extra gebe ich rechts neben dem Chatfenster noch eine Liste aller Teilnehmer von heute aus:<\/p>\n<pre>\/\/alle Teilnehmer von heute ausgeben\r\necho '&lt;div id=\"teilnehmer_fenster\" &gt;';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0echo '&lt;h2&gt;Heute im Chat:&lt;\/h2&gt;';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/Nur die Teilnehmer von heute auslesen\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $abfrage = mysqli_query($conn,\"SELECT <span style=\"color: #008000;\">DISTINCT<\/span> nick FROM $table WHERE datum LIKE '$datum'\"); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while($row = mysqli_fetch_array($abfrage,MYSQLI_ASSOC)) \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo $row['nick'].'&lt;br&gt;'; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\necho '&lt;\/div&gt;';<\/pre>\n<p>Jetzt noch ein wenig CSS-Kosmetik:<\/p>\n<pre>&lt;style type=\"text\/css\"&gt; \r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 #textbox{ \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 width:600px; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 border:1px solid blue; \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0#textbox1{ \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 width:80px; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 border:1px solid blue; \r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 #button{ \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 border:1px solid #FF1493; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cursor:pointer; \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 #button:hover{ \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 border:1px solid #3399FF; \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0#nick_und_message{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0<span style=\"color: #008000;\">width:80%;<\/span>\r\n<span style=\"color: #008000;\">\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0float:left;<\/span>\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0#uhrzeit {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0<span style=\"color: #008000;\">width:20%;<\/span>\r\n<span style=\"color: #008000;\">\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0float:right;<\/span>\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0<span style=\"color: #008000;\">text-align: right;<\/span>\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0#chat_fenster{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0border:2px solid blue;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0width:750px; \r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0height:350px; \r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0padding:3px; \r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0<span style=\"color: #ff0000;\">overflow: auto;<\/span>\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0float:left;\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0#teilnehmer_fenster{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0float:right;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0width:200px;\r\n\u00a0\u00a0 \u00a0}\r\n&lt;\/style&gt;<\/pre>\n<p>Wichtig ist hier der Eintrag overflow:auto f\u00fcr das Chatfenster, der sorgt f\u00fcr den Scrollbalken. Damit jetzt die bereits vorhandenen Eintr\u00e4ge nach oben wegscrollen und der letzte Eintrag immer im Chatfenster ganz unten auftaucht, noch ein kleiner Javascript-Trick:<\/p>\n<pre>&lt;script&gt;\r\nwindow.onload = function()\r\n{\r\n\/\/Chatfenster nach oben wegscrollen, damit immer die neuesten Eintr\u00e4ge sichtbar sind\r\ndocument.getElementById('chat_fenster').scrollTop = <span style=\"color: #008000;\">9999999<\/span>;\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>Man setzt einfach einen sehr hohen Wert f\u00fcr das Scrollen nach oben, damit ist die Liste immer nach oben weggescrollt und das Ende mit den neuesten Beitr\u00e4gen bleibt im sichtbaren Bereich.<\/p>\n<p>Das wars &#8211; viel Spa\u00df beim Nachbauen! Das liesse sich nat\u00fcrlich noch beliebig erweitern, in einem CMS k\u00f6nnte man z.B. den Chat nur f\u00fcr eingeloggte User freischalten, dann entf\u00e4llt das Abfragen des Nicks. Man k\u00f6nnte auch noch ein Chat-Archiv anlegen, in dem man die Beitr\u00e4ge der letzten Tage einsehen kann, und man k\u00f6nnte sonst noch allerhand Spielereien veranstalten, da kann sich jeder selber austoben. Ich lass es mal so stehen, als wirklich simple L\u00f6sung.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Da ich mich derzeit viel im Chat in meinem Lieblings-Handarbeitsforum herumtreibe, dachte ich mir: so einen kleinen, eher spartanischen Chatroom solltest du eigentlich auch selber programmieren k\u00f6nnen, das kann so schwierig nicht sein. Bei Google gibt es -zig Beispiele, wie man so etwas angehen k\u00f6nnte, ich hab mich auf die Suche nach etwas Einfachem gemacht [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1,20,21,11,47,7,4,63,59],"tags":[],"_links":{"self":[{"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/posts\/1461"}],"collection":[{"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/comments?post=1461"}],"version-history":[{"count":6,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/posts\/1461\/revisions"}],"predecessor-version":[{"id":1470,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/posts\/1461\/revisions\/1470"}],"wp:attachment":[{"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/media?parent=1461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/categories?post=1461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/evileu.de\/zum-schwarzen-pinguin\/wp-json\/wp\/v2\/tags?post=1461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}