{"id":1111,"date":"2015-11-05T09:18:12","date_gmt":"2015-11-05T09:18:12","guid":{"rendered":"https:\/\/anexia.com\/blog\/de\/?p=1111"},"modified":"2022-04-19T13:37:45","modified_gmt":"2022-04-19T11:37:45","slug":"mit-codeigniter-zum-eigenen-online-chat","status":"publish","type":"post","link":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/","title":{"rendered":"Mit CodeIgniter zum eigenen Online-Chat"},"content":{"rendered":"<p>Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook oder Google Plus, vorkommt.<!--more--><\/p>\n<p>Doch wie die Technik dahinter aussieht, und wie so ein Chat prinzipiell funktioniert m\u00f6chte ich euch im Folgenden erkl\u00e4ren.<\/p>\n<p>Im Anschluss daran gibt\u2019s auch ein Tutorial, wie ihr euch euren eigenen Chat mit Hilfe des CodeIgniter-Frameworks f\u00fcr eure n\u00e4chste <a href=\"https:\/\/anexia.com\/de\/softwareentwicklung\/webentwicklung\/\">Webentwicklung<\/a> bauen k\u00f6nnt.<\/p>\n<p><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1116 size-large\" src=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-1024x302.png\" alt=\"CodeIgniter Chat\" width=\"474\" height=\"140\" srcset=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-1024x302.png 1024w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-325x96.png 325w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat-300x89.png 300w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/10\/ci_chat.png 1175w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Das Prinzip dahinter<\/h2>\n<p>Grunds\u00e4tzlich unterscheidet man beim Online-Chat zwischen drei Formen:<\/p>\n<ul>\n<li>Internet Relay Chat (IRC)<\/li>\n<li>Webchat<\/li>\n<li>Instant Messaging<\/li>\n<\/ul>\n<p>Beim IRC kommt die klassische Form der Client-Server-Architektur ins Spiel. Hierbei werden spezielle Chat-Server ben\u00f6tigt, welche untereinander vernetzt sind. Mit einer geeigneten Client-Software, welche sich entweder direkt auf den PCs der jeweiligen Chatteilnehmer befindet bzw. \u00fcber deren Browser ausgef\u00fchrt wird, k\u00f6nnen untereinander Nachrichten ausgetauscht werden.<\/p>\n<p>Bei einfachen Webchat, wie er beispielsweise von Live-Support-Systemen verwendet wird, ist keine zus\u00e4tzliche Software notwendig. Meistens ist die Kommunikation auch auf die jeweilige Website beschr\u00e4nkt.<\/p>\n<p>Ganz anders sieht es allerdings beim Instant Messaging aus. Hier findet die Kommunikation in der Regel \u00fcber keinen \u00f6ffentlichen Chatraum statt, sondern ausschlie\u00dflich zwischen den jeweiligen Chatteilnehmern, welche sich \u00fcber eine entsprechende Software identifizieren.<\/p>\n<p>IRC und Instant Messaging bieten meistens noch weitere Funktionen, wie beispielsweise Gespr\u00e4chsprotokolle oder die \u00dcbertragung von Dateien.<\/p>\n<p>&nbsp;<\/p>\n<h2>Der eigene Chat mit CodeIgniter<\/h2>\n<p><a href=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-504\" src=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-300x70.png\" alt=\"CodeIgniter Logo\" width=\"300\" height=\"70\" srcset=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-300x70.png 300w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-600x140.png 600w, https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/codeigniter_logo-1024x239.png 1024w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>Grundstruktur vorbereiten<\/h3>\n<p>Um zu beginnen, laden wir uns zuerst die aktuellste Version des CodeIgniter-Frameworks von dessen Website (<a href=\"http:\/\/www.codeigniter.com\">http:\/\/www.codeigniter.com<\/a>) herunter. Dies ist in diesem Fall Version 3.0.2.<\/p>\n<p>Nun kopieren wir alle Dateien am besten in einen Unterordner \u201eci-chat\u201c auf den Webserver (z.B. XAMPP, LAMP, etc.) und rufen dessen Rootverzeichnis im Browser auf, z.B. http:\/\/localhost\/ci-chat\/.<\/p>\n<p>Wenn alle Anforderungen des Frameworks erf\u00fcllt sind, sollte hier nun die Willkommensseite von CodeIgniter sichtbar sein.<\/p>\n<p>In der Autoloader-Konfiguration unter <strong>\/application\/config\/autoload.php<\/strong> f\u00fcgen wir als n\u00e4chstes den URL-Helper sowie die Datenbank-Library hinzu, da wir diese Komponenten sp\u00e4ter brauchen werden.<\/p>\n<pre class=\"lang:php decode:true \">$autoload['libraries'] = array('database');\r\n$autoload['helper'] = array('url');<\/pre>\n<p>In der Routenkonfiguration unter <strong>\/application\/config\/routes.php<\/strong> \u00e4ndern wir als n\u00e4chstes den Standard-Controller von \u201e<em>welcome<\/em>\u201c auf \u201e<em>chat<\/em>\u201c, da wir sp\u00e4ter m\u00f6chten, dass standardm\u00e4\u00dfig unsere Chat-Applikation aufgerufen wird.<\/p>\n<pre class=\"lang:php decode:true \">$route['default_controller'] = 'chat';<\/pre>\n<p>&nbsp;<\/p>\n<h3>Die eigentliche Applikation<\/h3>\n<p>Momentan w\u00fcrde die Routenkonfiguration nur einen 404-Fehler verursachen, da wir bislang noch keinen Chat-Controller definiert haben.<\/p>\n<p>Aus diesem Grund erstellen wir unter <strong>\/application\/controllers<\/strong> einen neuen namens <strong>Chat.php<\/strong> und schreiben hier folgendes hinein:<\/p>\n<pre class=\"lang:php decode:true \">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Chat extends CI_Controller {\r\n\r\n\r\n\tpublic function index()\r\n\t{\r\n\t\t$this-&gt;load-&gt;view('chat');\r\n\t}\r\n}\r\n<\/pre>\n<p>Dieser Controller wirkt nicht nur primitiv, er ist es auch. Seine einzige Aufgabe liegt darin, die entsprechende View zu laden. F\u00fcr die eigentliche Funktion kommt ein separater API-Controller ins Spiel.<\/p>\n<p>Selbstverst\u00e4ndlich k\u00f6nnte man die gesamte Logik auch in den zuvor erstellten Controller unterbringen. Die Aufteilung in mehrere Controller macht vor allem bei gr\u00f6\u00dferen Projekten Sinn, da dies die Lesbarkeit und die damit in Verbindung stehende Wartbarkeit wesentlich erh\u00f6ht.<\/p>\n<p>&nbsp;<\/p>\n<p>Um die einzelnen Nachrichten zu speichern, um diese sp\u00e4ter auch den anderen Chatteilnehmern auszuliefern, brauchen wir eine Datenbank sowie ein geeignetes Model.<\/p>\n<pre class=\"lang:vim decode:true \">CREATE TABLE IF NOT EXISTS `messages` (\r\n`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,\r\n`message` text NOT NULL,\r\n`nickname` varchar(50) NOT NULL,\r\n`guid` varchar(100) NOT NULL,\r\n`timestamp` int(11) NOT NULL\r\n);\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Nun erstellen wir unter <strong>\/application\/models<\/strong> ein neues Model namens <strong>Chat_model.php<\/strong> und f\u00fcgen folgenden Inhalt ein:<\/p>\n<pre class=\"lang:php decode:true \">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Chat_model extends CI_Model {  \r\n  \r\n\tfunction add_message($message, $nickname, $guid)\r\n\t{\r\n\t\t$data = array(\r\n\t\t\t'message'\t=&gt; (string) $message,\r\n\t\t\t'nickname'\t=&gt; (string) $nickname,\r\n\t\t\t'guid'\t\t=&gt; (string)\t$guid,\r\n\t\t\t'timestamp'\t=&gt; time(),\r\n\t\t);\r\n\t\t  \r\n\t\t$this-&gt;db-&gt;insert('messages', $data);\r\n\t}\r\n\r\n\tfunction get_messages($timestamp)\r\n\t{\r\n\t\t$this-&gt;db-&gt;where('timestamp &gt;', $timestamp);\r\n\t\t$this-&gt;db-&gt;order_by('timestamp', 'DESC');\r\n\t\t$this-&gt;db-&gt;limit(10); \r\n\t\t$query = $this-&gt;db-&gt;get('messages');\r\n\t\t\r\n\t\treturn array_reverse($query-&gt;result_array());\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>Die Methode <strong>add_message()<\/strong> erm\u00f6glicht es uns, neue Nachrichten hinzuzuf\u00fcgen und erwartet als Parameter die eigentliche Nachricht und den Nickname des Chatteilnehmers, von welchem die Nachricht stammt. Um Konflikte zu vermeiden, wenn mehrere Chatteilnehmer den gleichen Nickname verwenden sollten, werden wir zus\u00e4tzlich eine GUID mitspeichern. Dies ist eine eindeutige Kennung, welche sp\u00e4ter nur von der Applikation selbst ausgewertet werden wird.<\/p>\n<p>Mittels <strong>get_messages()<\/strong> bekommen wir alle Nachrichten, welche von einem bestimmten Zeitpunkt ausgehend geschrieben wurden. Diese Methode erwartet hierf\u00fcr den jeweiligen UNIX-Zeitstempel.<\/p>\n<p>&nbsp;<\/p>\n<p>Um nun diese beiden Methoden nach au\u00dfen hin verf\u00fcgbar zu machen, legen wir unter <strong>\/application\/controllers<\/strong> einen neuen Controller <strong>Api.php<\/strong> an und schreiben hier folgendes hinein:<\/p>\n<pre class=\"lang:php decode:true \">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n\r\nclass Api extends CI_Controller {\r\n\r\n\t\r\n\tpublic function __construct()\r\n\t{\r\n\t\tparent::__construct();\r\n\t\t\r\n\t\t$this-&gt;load-&gt;model('Chat_model');\r\n\t}\r\n\t\r\n\t\t\r\n\tpublic function send_message()\r\n\t{\r\n\t\t$message = $this-&gt;input-&gt;get('message', null);\r\n\t\t$nickname = $this-&gt;input-&gt;get('nickname', '');\r\n\t\t$guid = $this-&gt;input-&gt;get('guid', '');\r\n\t\t\r\n\t\t$this-&gt;Chat_model-&gt;add_message($message, $nickname, $guid);\r\n\t\t\r\n\t\t$this-&gt;_setOutput($message);\r\n\t}\r\n\t\r\n\t\r\n\tpublic function get_messages()\r\n\t{\r\n\t\t$timestamp = $this-&gt;input-&gt;get('timestamp', null);\r\n\t\t\r\n\t\t$messages = $this-&gt;Chat_model-&gt;get_messages($timestamp);\r\n\t\t\r\n\t\t$this-&gt;_setOutput($messages);\r\n\t}\r\n\t\r\n\t\r\n\tprivate function _setOutput($data)\r\n\t{\r\n\t\theader('Cache-Control: no-cache, must-revalidate');\r\n\t\theader('Expires: Mon, 26 Jul 1997 05:00:00 GMT');\r\n\t\theader('Content-type: application\/json');\r\n\t\t\r\n\t\techo json_encode($data);\r\n\t}\r\n}<\/pre>\n<p>Im Konstruktur wird nun das zuvor erstellte Chat-Model geladen. Des Weiteren wird via <strong>_setOutput()<\/strong> ein zentraler Output-Handler bereitgestellt, welchem wir einfach die notwendigen Daten \u00fcbergeben und diese dann entsprechend aufbereitet werden (in diesem Fall JSON).<\/p>\n<p>&nbsp;<\/p>\n<h3>Die grafische Oberfl\u00e4che<\/h3>\n<p>Unter <strong>\/application\/views<\/strong> erstellen wir eine neue View <strong>chat.php<\/strong> (welche wir zuvor im Chat-Controller bereits verlinkt haben).<\/p>\n<p>In dieser bauen wir uns das HTML-Grundger\u00fcst unseres Chats auf. Basierend auf jQuery und Bootstrap.<\/p>\n<pre class=\"lang:vim decode:true\">&lt;?php\r\ndefined('BASEPATH') OR exit('No direct script access allowed');\r\n?&gt;&lt;!DOCTYPE html&gt;\r\n&lt;html lang=\"en\"&gt;\r\n&lt;head&gt;\r\n\t&lt;meta charset=\"utf-8\"&gt;\r\n\t&lt;title&gt;Chat-Example | CodeIgniter&lt;\/title&gt;\r\n\t\r\n\t&lt;script type=\"text\/javascript\" src=\"https:\/\/code.jquery.com\/jquery-2.1.4.min.js\"&gt;&lt;\/script&gt;\r\n\r\n\t\t\r\n\t&lt;link rel=\"stylesheet\" href=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.5\/css\/bootstrap.min.css\" \/&gt;\r\n\t&lt;script type=\"text\/javascript\" src=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.5\/js\/bootstrap.min.js\"&gt;&lt;\/script&gt;\r\n\t\r\n\t&lt;!-- http:\/\/bootsnipp.com\/snippets\/4jXW --&gt;\r\n\t&lt;link rel=\"stylesheet\" href=\"&lt;?php echo base_url(); ?&gt;assets\/css\/chat.css\" \/&gt;\r\n\t\r\n\t\r\n\t&lt;script type=\"text\/javascript\"&gt;\t  \r\n\t\t$( document ).ready ( function () {\r\n\t\t\t\r\n\t\t\t$('#nickname').keyup(function() {\r\n\t\t\t\tvar nickname = $(this).val();\r\n\t\t\t\t\r\n\t\t\t\tif(nickname == ''){\r\n\t\t\t\t\t$('#msg_block').hide();\r\n\t\t\t\t}else{\r\n\t\t\t\t\t$('#msg_block').show();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\t\r\n\t\t\t\/\/ initial nickname check\r\n\t\t\t$('#nickname').trigger('keyup');\r\n\t\t});\r\n\t\t\r\n\t\t\r\n\t&lt;\/script&gt;\r\n\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n\r\n\r\n\r\n&lt;div class=\"container\"&gt;\r\n    &lt;div class=\"row\"&gt;\r\n\t\t&lt;div class=\"panel panel-primary\"&gt;\r\n\t\t\t&lt;div class=\"panel-heading\"&gt;\r\n\t\t\t\t&lt;span class=\"glyphicon glyphicon-comment\"&gt;&lt;\/span&gt; Chat\r\n\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;div class=\"panel-body\"&gt;\r\n\t\t\t\t&lt;ul class=\"chat\" id=\"received\"&gt;\r\n\t\t\t\t\t\r\n\t\t\t\t&lt;\/ul&gt;\r\n\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;div class=\"panel-footer\"&gt;\r\n\t\t\t\t&lt;div class=\"clearfix\"&gt;\r\n\t\t\t\t\t&lt;div class=\"col-md-3\"&gt;\r\n\t\t\t\t\t\t&lt;div class=\"input-group\"&gt;\r\n\t\t\t\t\t\t\t&lt;span class=\"input-group-addon\"&gt;\r\n\t\t\t\t\t\t\t\tNickname:\r\n\t\t\t\t\t\t\t&lt;\/span&gt;\r\n\t\t\t\t\t\t\t&lt;input id=\"nickname\" type=\"text\" class=\"form-control input-sm\" placeholder=\"Nickname...\" \/&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;div class=\"col-md-9\" id=\"msg_block\"&gt;\r\n\t\t\t\t\t\t&lt;div class=\"input-group\"&gt;\r\n\t\t\t\t\t\t\t&lt;input id=\"message\" type=\"text\" class=\"form-control input-sm\" placeholder=\"Type your message here...\" \/&gt;\r\n\t\t\t\t\t\t\t&lt;span class=\"input-group-btn\"&gt;\r\n\t\t\t\t\t\t\t\t&lt;button class=\"btn btn-warning btn-sm\" id=\"submit\"&gt;Send&lt;\/button&gt;\r\n\t\t\t\t\t\t\t&lt;\/span&gt;\r\n\t\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t\t&lt;\/div&gt;\r\n\t\t\t\t&lt;\/div&gt;\r\n\t\t\t&lt;\/div&gt;\r\n\t\t&lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n\r\n\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>Im Javascript-Block befindet sich ein Check, sodass das Eingabefeld f\u00fcr die Chatnachrichten erst dann sichtbar ist, wenn der Benutzer einen Nickname eingegeben hat.<\/p>\n<p>Damit das ganze nun auch grafisch entsprechend gut aussieht, legen wir noch eine <strong>chat.css<\/strong> mit folgendem Inhalt an:<\/p>\n<pre class=\"lang:css decode:true\">.chat\r\n{\r\n    list-style: none;\r\n    margin: 0;\r\n    padding: 0;\r\n}\r\n\r\n.chat li\r\n{\r\n    margin-bottom: 10px;\r\n    padding-bottom: 5px;\r\n    border-bottom: 1px dotted #B3A9A9;\r\n}\r\n\r\n.chat li.left .chat-body\r\n{\r\n    margin-left: 60px;\r\n}\r\n\r\n.chat li.right .chat-body\r\n{\r\n    margin-right: 60px;\r\n}\r\n\r\n\r\n.chat li .chat-body p\r\n{\r\n    margin: 0;\r\n    color: #777777;\r\n}\r\n\r\n.panel .slidedown .glyphicon, .chat .glyphicon\r\n{\r\n    margin-right: 5px;\r\n}\r\n\r\n.panel-body\r\n{\r\n    overflow-y: scroll;\r\n    height: 250px;\r\n}\r\n\r\n::-webkit-scrollbar-track\r\n{\r\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);\r\n    background-color: #F5F5F5;\r\n}\r\n\r\n::-webkit-scrollbar\r\n{\r\n    width: 12px;\r\n    background-color: #F5F5F5;\r\n}\r\n\r\n::-webkit-scrollbar-thumb\r\n{\r\n    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\r\n    background-color: #555;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Im n\u00e4chsten Schritt definieren wir hier noch zus\u00e4tzliche Hilfsfunktionen und speichern hier auch die GUID des Chatteilnehmers in Form eines Cookies. Der Einfachheit halber wird diese Kennung nur lokal im Browser generiert. In einer produktiven Umgebung k\u00f6nnte diese beispielweise in einer User-Tabelle direkt in der Datenbank gespeichert werden.<\/p>\n<pre class=\"lang:js decode:true \">var request_timestamp = 0;\r\n\r\nvar setCookie = function(key, value) {\r\n\tvar expires = new Date();\r\n\texpires.setTime(expires.getTime() + (5 * 60 * 1000));\r\n\tdocument.cookie = key + '=' + value + ';expires=' + expires.toUTCString();\r\n}\r\n\r\nvar getCookie = function(key) {\r\n\tvar keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');\r\n\treturn keyValue ? keyValue[2] : null;\r\n}\r\n\r\nvar guid = function() {\r\n\tfunction s4() {\r\n\t\treturn Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\r\n\t}\r\n\treturn s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();\r\n}\r\n\r\nif(getCookie('user_guid') == null || typeof(getCookie('user_guid')) == 'undefined'){\r\n\tvar user_guid = guid();\r\n\tsetCookie('user_guid', user_guid);\r\n}\r\n\r\n\r\n\/\/ https:\/\/gist.github.com\/kmaida\/6045266\r\nvar parseTimestamp = function(timestamp) {\r\n\tvar d = new Date( timestamp * 1000 ), \/\/ milliseconds\r\n\t\tyyyy = d.getFullYear(),\r\n\t\tmm = ('0' + (d.getMonth() + 1)).slice(-2),\t\/\/ Months are zero based. Add leading 0.\r\n\t\tdd = ('0' + d.getDate()).slice(-2),\t\t\t\/\/ Add leading 0.\r\n\t\thh = d.getHours(),\r\n\t\th = hh,\r\n\t\tmin = ('0' + d.getMinutes()).slice(-2),\t\t\/\/ Add leading 0.\r\n\t\tampm = 'AM',\r\n\t\ttimeString;\r\n\t\t\t\r\n\tif (hh &gt; 12) {\r\n\t\th = hh - 12;\r\n\t\tampm = 'PM';\r\n\t} else if (hh === 12) {\r\n\t\th = 12;\r\n\t\tampm = 'PM';\r\n\t} else if (hh == 0) {\r\n\t\th = 12;\r\n\t}\r\n\r\n\ttimeString = yyyy + '-' + mm + '-' + dd + ', ' + h + ':' + min + ' ' + ampm;\r\n\t\t\r\n\treturn timeString;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Nun definieren wir die eigentlichen Funktionen in Form von Closures f\u00fcr das Hinzuf\u00fcgen von Nachrichten und dem Auslesen dieser.<\/p>\n<pre class=\"lang:vim decode:true \">var sendChat = function (message, callback) {\r\n\t$.getJSON('&lt;?php echo base_url(); ?&gt;api\/send_message?message=' + message + '&amp;nickname=' + $('#nickname').val() + '&amp;guid=' + getCookie('user_guid'), function (data){\r\n\t\tcallback();\r\n\t});\r\n}\r\n\r\nvar append_chat_data = function (chat_data) {\r\n\tchat_data.forEach(function (data) {\r\n\t\tvar is_me = data.guid == getCookie('user_guid');\r\n\t\t\r\n\t\tif(is_me){\r\n\t\t\tvar html = '&lt;li class=\"right clearfix\"&gt;';\r\n\t\t\thtml += '\t&lt;span class=\"chat-img pull-right\"&gt;';\r\n\t\t\thtml += '\t\t&lt;img src=\"http:\/\/placehold.it\/50\/FA6F57\/fff&amp;text=' + data.nickname.slice(0,2) + '\" alt=\"User Avatar\" class=\"img-circle\" \/&gt;';\r\n\t\t\thtml += '\t&lt;\/span&gt;';\r\n\t\t\thtml += '\t&lt;div class=\"chat-body clearfix\"&gt;';\r\n\t\t\thtml += '\t\t&lt;div class=\"header\"&gt;';\r\n\t\t\thtml += '\t\t\t&lt;small class=\"text-muted\"&gt;&lt;span class=\"glyphicon glyphicon-time\"&gt;&lt;\/span&gt;' + parseTimestamp(data.timestamp) + '&lt;\/small&gt;';\r\n\t\t\thtml += '\t\t\t&lt;strong class=\"pull-right primary-font\"&gt;' + data.nickname + '&lt;\/strong&gt;';\r\n\t\t\thtml += '\t\t&lt;\/div&gt;';\r\n\t\t\thtml += '\t\t&lt;p&gt;' + data.message + '&lt;\/p&gt;';\r\n\t\t\thtml += '\t&lt;\/div&gt;';\r\n\t\t\thtml += '&lt;\/li&gt;';\r\n\t\t}else{\r\n\t\t  \r\n\t\t\tvar html = '&lt;li class=\"left clearfix\"&gt;';\r\n\t\t\thtml += '\t&lt;span class=\"chat-img pull-left\"&gt;';\r\n\t\t\thtml += '\t\t&lt;img src=\"http:\/\/placehold.it\/50\/55C1E7\/fff&amp;text=' + data.nickname.slice(0,2) + '\" alt=\"User Avatar\" class=\"img-circle\" \/&gt;';\r\n\t\t\thtml += '\t&lt;\/span&gt;';\r\n\t\t\thtml += '\t&lt;div class=\"chat-body clearfix\"&gt;';\r\n\t\t\thtml += '\t\t&lt;div class=\"header\"&gt;';\r\n\t\t\thtml += '\t\t\t&lt;strong class=\"primary-font\"&gt;' + data.nickname + '&lt;\/strong&gt;';\r\n\t\t\thtml += '\t\t\t&lt;small class=\"pull-right text-muted\"&gt;&lt;span class=\"glyphicon glyphicon-time\"&gt;&lt;\/span&gt;' + parseTimestamp(data.timestamp) + '&lt;\/small&gt;';\r\n\t\t\t\r\n\t\t\thtml += '\t\t&lt;\/div&gt;';\r\n\t\t\thtml += '\t\t&lt;p&gt;' + data.message + '&lt;\/p&gt;';\r\n\t\t\thtml += '\t&lt;\/div&gt;';\r\n\t\t\thtml += '&lt;\/li&gt;';\r\n\t\t}\r\n\t\t$(\"#received\").html( $(\"#received\").html() + html);\r\n\t});\r\n  \r\n\t$('#received').animate({ scrollTop: $('#received').height()}, 1000);\r\n}\r\n\r\nvar update_chats = function () {\r\n\tif(typeof(request_timestamp) == 'undefined' || request_timestamp == 0){\r\n\t\tvar offset = 60*15; \/\/ 15min\r\n\t\trequest_timestamp = parseInt( Date.now() \/ 1000 - offset );\r\n\t}\r\n\t$.getJSON('&lt;?php echo base_url(); ?&gt;api\/get_messages?timestamp=' + request_timestamp, function (data){\r\n\t\tappend_chat_data(data);\t\r\n\r\n\t\tvar newIndex = data.length-1;\r\n\t\tif(typeof(data[newIndex]) != 'undefined'){\r\n\t\t\trequest_timestamp = data[newIndex].timestamp;\r\n\t\t}\r\n\t});      \r\n}<\/pre>\n<p>Der Einfachheit halber wird in <strong>append_chat_data()<\/strong> das HTML-Markup direkt zusammengebaut. Die Daten selbst sollten am besten entweder an eigene Render-Funktionen \u00fcbergeben werden, oder gleich eine richtige Javascript-Template-Engine verwendet werden.<\/p>\n<p>Dies w\u00fcrde jedoch den Rahmen f\u00fcr dieses Beispiel hier bei weitem sprengen, daher diese primitive L\u00f6sung.<\/p>\n<p>&nbsp;<\/p>\n<p>Nun definieren wir das Verhalten der GUI selbst.<\/p>\n<pre class=\"lang:js decode:true\">$('#submit').click(function (e) {\r\n\te.preventDefault();\r\n\t\r\n\tvar $field = $('#message');\r\n\tvar data = $field.val();\r\n\r\n\t$field.addClass('disabled').attr('disabled', 'disabled');\r\n\tsendChat(data, function (){\r\n\t\t$field.val('').removeClass('disabled').removeAttr('disabled');\r\n\t});\r\n});\r\n\r\n$('#message').keyup(function (e) {\r\n\tif (e.which == 13) {\r\n\t\t$('#submit').trigger('click');\r\n\t}\r\n});\r\n\r\nsetInterval(function (){\r\n\tupdate_chats();\r\n}, 1500);<\/pre>\n<p>Dieser Code erm\u00f6glicht es, die eingegebenen Nachrichten mit einem Klick auf die Enter-Taste direkt abzusenden, und sperrt das Feld so lange, bis die Nachricht vom Server verarbeitet wurde. Im Callback von <strong>sendChat()<\/strong> wird dieses Feld danach wieder freigegeben.<\/p>\n<p>Um stets alle Nachrichten nahezu in Echtzeit zu erhalten, wird die Funktion<strong> update_chats()<\/strong> im Intervall von 1,5 Sekunden aufgerufen. Diese pr\u00fcft anhand des jeweiligen Zeitstempels, ob es neue Nachrichten gibt oder nicht und f\u00fcgt diese dann dem Chatfenster hinzu.<\/p>\n<p>&nbsp;<\/p>\n<h2>Fazit<\/h2>\n<p>Die in diesem Beispiel gezeigte Form einer Chat-Integration verursacht durch die zahlreichen Abfragen eine relativ hohe Last auf dem Datenbankserver.<\/p>\n<p>F\u00fcr gr\u00f6\u00dfere Websites w\u00e4re es jedoch ratsam auf eine entsprechende Infrastruktur zu setzen, d.h. ein geeignetes Chat-Protokoll (z.B. XMPP) und danach eine geeignete Integrationsm\u00f6glichkeit auszuw\u00e4hlen.<\/p>\n<p>Dieses Beispiel sollte mehr als Lernbeispiel dienen, kann aber auf kleineren weniger stark frequentierten Websites auch produktiv genutzt werden.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Hinweis:<\/strong> Dieses Beispiel setzt ein Grundwissen im Umgang mit dem CodeIgniter-Framework voraus (siehe <a href=\"https:\/\/anexia.com\/blog\/de\/schnelleinstieg-ins-codeigniter-framework\/\">Schnelleinstieg ins CodeIgniter-Framework<\/a>) und nutzt teilweise quelloffene Codeschnipsel von <a href=\"http:\/\/bootswatch.com\/\" target=\"_blank\" rel=\"noopener\">Bootswatch.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.<\/p>\n","protected":false},"author":15,"featured_media":515,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[205,78,73,207,208,206,14,5,77],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog<\/title>\n<meta name=\"description\" content=\"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog\" \/>\n<meta property=\"og:description\" content=\"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/\" \/>\n<meta property=\"og:site_name\" content=\"ANEXIA Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/anexiagmbh\/\" \/>\n<meta property=\"article:published_time\" content=\"2015-11-05T09:18:12+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-04-19T11:37:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"1067\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manuel Wutte\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:site\" content=\"@_ANEXIA\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manuel Wutte\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"12\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/\",\"url\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/\",\"name\":\"Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog\",\"isPartOf\":{\"@id\":\"https:\/\/anexia.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"datePublished\":\"2015-11-05T09:18:12+00:00\",\"dateModified\":\"2022-04-19T11:37:45+00:00\",\"author\":{\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\"},\"description\":\"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.\",\"breadcrumb\":{\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage\",\"url\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"contentUrl\":\"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg\",\"width\":1600,\"height\":1067},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/anexia.com\/blog\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Mit CodeIgniter zum eigenen Online-Chat\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/anexia.com\/blog\/#website\",\"url\":\"https:\/\/anexia.com\/blog\/\",\"name\":\"ANEXIA Blog\",\"description\":\"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/anexia.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de\",\"name\":\"Manuel Wutte\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g\",\"caption\":\"Manuel Wutte\"},\"url\":\"https:\/\/anexia.com\/blog\/author\/mwu\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog","description":"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/","og_locale":"de_DE","og_type":"article","og_title":"Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog","og_description":"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.","og_url":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/","og_site_name":"ANEXIA Blog","article_publisher":"https:\/\/www.facebook.com\/anexiagmbh\/","article_published_time":"2015-11-05T09:18:12+00:00","article_modified_time":"2022-04-19T11:37:45+00:00","og_image":[{"width":1600,"height":1067,"url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","type":"image\/jpeg"}],"author":"Manuel Wutte","twitter_card":"summary_large_image","twitter_creator":"@_ANEXIA","twitter_site":"@_ANEXIA","twitter_misc":{"Verfasst von":"Manuel Wutte","Gesch\u00e4tzte Lesezeit":"12\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/","url":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/","name":"Mit CodeIgniter zum eigenen Online-Chat - ANEXIA Blog","isPartOf":{"@id":"https:\/\/anexia.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage"},"image":{"@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage"},"thumbnailUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","datePublished":"2015-11-05T09:18:12+00:00","dateModified":"2022-04-19T11:37:45+00:00","author":{"@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de"},"description":"Jeder kennt ihn oder hat ihn zumindest schon mal gesehen \u2013 die Rede ist vom Online-Chat, wie er auf vielen Websites, wie beispielsweise Facebook vorkommt.","breadcrumb":{"@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#primaryimage","url":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","contentUrl":"https:\/\/anexia.com\/blog\/wp-content\/uploads\/2015\/01\/Manuel-Wutte_anexia-blau_web.jpg","width":1600,"height":1067},{"@type":"BreadcrumbList","@id":"https:\/\/anexia.com\/blog\/de\/mit-codeigniter-zum-eigenen-online-chat\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/anexia.com\/blog\/de\/"},{"@type":"ListItem","position":2,"name":"Mit CodeIgniter zum eigenen Online-Chat"}]},{"@type":"WebSite","@id":"https:\/\/anexia.com\/blog\/#website","url":"https:\/\/anexia.com\/blog\/","name":"ANEXIA Blog","description":"[:de] ANEXIA Blog - Technischen Themen, Anexia News und Insights [:]","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/anexia.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/926f6b9e5aeed88b145cf86d87fd09de","name":"Manuel Wutte","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/anexia.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9528a61f48f4294cd5f7cd8a4141bd55?s=96&d=mm&r=g","caption":"Manuel Wutte"},"url":"https:\/\/anexia.com\/blog\/author\/mwu\/"}]}},"lang":"de","translations":{"de":1111,"en":6970},"amp_enabled":true,"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/1111"}],"collection":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/comments?post=1111"}],"version-history":[{"count":33,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/1111\/revisions"}],"predecessor-version":[{"id":6972,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/posts\/1111\/revisions\/6972"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media\/515"}],"wp:attachment":[{"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/media?parent=1111"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/categories?post=1111"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anexia.com\/blog\/wp-json\/wp\/v2\/tags?post=1111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}