我正在使用php开发一个简单的聊天应用程序。 我使用ajax将消息插入数据库,并且每5秒钟后我重新加载页面,这样如果有任何新消息到达它会刷新,用户将能够看到新消息,但这不是一个好方法。我想要一个解决方案,以便如果有任何新消息到达,用户可以看到没有重新加载页面后每5秒。 我用过的javascript代码是:
$(document).ready(function() {
debugger;
var percentageToScroll = 100;
var height = $('.panel-body').innerHeight();
var scrollAmount = height;
var overheight = jQuery(document).height() - jQuery(window).height();
jQuery(".divcls").animate({scrollTop: scrollAmount}, 900);
});
setTimeout(function(){
window.location.reload(1);
}, 5000);
function checkMsg()
{
//alert("Enter");
var message = document.getElementById("msg").value;
//alert(message);
if (message === "")
{
alert("Please Enter Message");
} else
{
submitChat(message);
}
}
;
function submitChat(message)
{
// alert("Enter");
var msg = message;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById('msg').innerHTML = "";
location.reload();
}
}
xmlhttp.open('GET', 'insert.php?msg=' + msg, true);
xmlhttp.send();
};
主页聊天框的代码段是:
<div style="overflow: scroll ;max-height: 650px; width: 100%;" class="divcls">
<div class="panel-body">
<ul class="media-list">
<?php
include './connect.php';
$sql = "select * from chatlog";
$result = mysqli_query($con,$sql);
while ($row = mysqli_fetch_array($result)) {
?>
<li class="media">
<div class="media-body">
<div class="media">
<a class="pull-left" href="#">
<img class="media-object img-circle " src="assets/img/user.png" />
</a>
<div class="media-body">
<span id="chatData"><?php echo $row["Msg"]; ?></span>
<br/>
<small class="text-muted"><?php echo $row["UserName"]; ?> | 23rd June at 5:00pm</small>
<hr />
</div>
</div>
</div>
</li>
<?php
}
?>
</ul>
</div>
</div>
插入页面:
<?php
require("connect.php");
$msg=$_GET['msg'];
$result=mysqli_query($con, "INSERT INTO chatlog(UserName, Msg) VALUES('admin','$msg')");
header("location:index.php");
?>
答案 0 :(得分:0)
警告:这个答案很长。所以,拿起你的咖啡做好准备。
首先,我想谈谈这段代码:
<?php
require("connect.php");
$msg=$_GET['msg'];
$result=mysqli_query($con, "INSERT INTO chatlog(UserName, Msg) VALUES('admin','$msg')");
header("location:index.php");
?>
请告诉我这不是您的源代码的直接复制和粘贴?如果是这样,您非常需要编辑它以防止SQL注入。为此,请尝试使用以下内容:
<?php
require("connect.php");
$msg= $con->real_escape_string($_GET['msg']);
$result=mysqli_query($con, "INSERT INTO chatlog(UserName, Msg) VALUES('admin','$msg')");
header("location:index.php");
?>
您可能还想考虑使用预准备语句,但real_escape_string()
至少会通过转义可能有害的消息来阻止注入。考虑阅读this SO Question以获取有关防止SQL注入攻击的最佳实践的更多信息。作为附加安全说明,您还应该考虑应用过滤器来防止XSS。
无论如何,我知道这不是你问题的主题,但是当我看到它们时,我总是倾向于提到这些缺陷。 (修复它们会保护您,您的网站和您的用户。)除了您的实际问题之外!
我见过很多“聊天框”实现,其中大多数都是以两种方式之一工作的:
localStorage
或sessionStorage
),网页使用上次收到的消息的ID查询后端脚本,后端脚本返回任何消息自该ID以来已收到(任何比上次收到的消息更新的消息)。就个人而言,我是第二种方法的粉丝,但有时第一种方法更容易实现。此外,要使用第二种方法,您的数据库需要在聊天记录条目中存储自动递增的唯一标识符。
方法一实施
因为第二种方法可能会因为你的方式而有点复杂,所以我会写一个第一种方法的例子。
以下是我将被轮询的后端PHP代码(我们称之为get_chat.php
):
<?php
// File: backend/get_chat.php
require_once('./connect.php');
$sql = "select * from chatlog";
$result = mysqli_query($con,$sql);
while ($row = mysqli_fetch_array($result)) {
?>
<li class="media">
<div class="media-body">
<div class="media">
<a class="pull-left" href="#">
<img class="media-object img-circle " src="assets/img/user.png" />
</a>
<div class="media-body">
<span id="chatData"><?php echo $row["Msg"]; ?></span>
<br/>
<small class="text-muted"><?php echo $row["UserName"]; ?> | 23rd June at 5:00pm</small>
<hr />
</div>
</div>
</div>
</li>
<?php
} /* End While Loop */
?>
注意:此代码将生成id="chatData"
的多个跨度。我已经离开了这样的代码,因为这也是你的原始代码所做的。但是,您不应该重复ID。我会在你认为合适的情况下由你来解决。
接下来,我们需要Javascript与此代码进行交互:
// We will want to set an initial timeout to start the refreshChat() 'cycle' (so to speak)
var timerId = setTimeout(function(){
refreshChat();
},
3000
); /* End setTimeout(); */
function refreshChat(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4) { // Request finished
// Check if the status code indicates success
if(xmlhttp.status === 200){
var chatbox = document.getElementById('chatBox');
chatbox.innerHTML = xmlhttp.responseText; // Set the inner-chatbox body
} // Else, something went wrong.
// Regardless of whether or not the request succeeded, the request has finished
// so we should now set up a new timeout to automatically refresh the window again.
// First, we'll try to clear the timeout so we don't potentially end up with two timeouts (which, in theory, would only happen if there is an error):
clearTimeout(timerId);
// Now we'll just go ahead and set the new timeout:
timerId = setTimeout(function(){
refreshChat();
},
3000
); /* End setTimeout(); */
}
} // End readyStateChange function
var cacheBreaker = new Date().getTime(); // Current time to prevent caching
xmlhttp.open('GET', 'backend/get_chat.php?anticache=' + cacheBreaker, true);
xmlhttp.send();
};
好的,现在我们有Javascript调用PHP脚本,然后接收所有最新聊天消息的HTML。但是,我们还没有完成。现在我们需要指定HTML的去向。在Javascript中我们说document.getElementById('chatBox');
,但我们目前实际上没有任何ID chatBox 的元素。
要解决此问题,并将重新加载的HTML放到正确的位置,我们需要做的就是将<ul class="media-list">
更改为<ul id="chatBox" class="media-list">
。现在,Javascript将知道我们将返回的HTML插入哪个元素,并且它将能够更新消息列表。
但我们还没有完成。现在我们需要对submitChat(message)
函数进行实际操作。我们不希望它重新加载页面,对吗?我们可能不希望用户提交消息,然后在出现之前必须等待3秒钟,因此,我们应该用以下内容替换submitChat()
:
function submitChat(message){
// alert("Enter");
var msg = message;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
// Handle this the same we handle refreshing the chat:
if (xmlhttp.readyState === 4) { // Request finished
// Check if the status code indicates success
if(xmlhttp.status === 200){
var chatbox = document.getElementById('chatBox');
chatbox.innerHTML = xmlhttp.responseText; // Set the inner-chatbox body
} // Else, something went wrong.
// First, we'll try to clear the timeout so we don't prematurely run refreshChat():
clearTimeout(timerId);
// Now we'll just go ahead and set the new timeout:
timerId = setTimeout(function(){
refreshChat();
},
3000
); /* End setTimeout(); */
}
}
xmlhttp.open('GET', 'insert.php?msg=' + msg, true);
xmlhttp.send();
};
现在,要使用这个新的Javascript,我们需要稍微修改我们的insert.php
代码:
<?php
require("connect.php");
$msg= $con->real_escape_string($_GET['msg']);
$result=mysqli_query($con, "INSERT INTO chatlog(UserName, Msg) VALUES('admin','$msg')");
// And now we'll return the newest messages in the database:
include_once('get_chat.php');
?>
就是这样。我们现在有一个聊天框,它会自动刷新自己,允许某人发布消息,并且具有针对SQL注入攻击的基本保护。
同样,我建议您考虑添加XSS保护,您可能需要考虑使用上述第二种方法来编写它。但是,方法二在这里实现起来太长且太复杂,而且XSS保护不在本问题的范围内,所以我将把这些留给你。
注意:我尚未在此处测试代码,因此可能包含一些错误。我试图通读所有代码来仔细检查它,但我确信我错过了一些小错误。尽管如此,这应该让你开始走正确的道路。如果某些事情没有意义,请不要犹豫,发表评论并询问。