我正在尝试实施点击计数系统。我在此链接Click here to see code中使用以下代码,但将其更改为现代标准。最初我收到了msqli_real_escape_字符串的错误,但我相信我解决了它(没有错误)。现在,我没有收到任何错误,但查询没有发送到我的数据库。我正在使用ini_set('display_errors', 1);
error_reporting(E_ALL);
进行错误检查。我还调用了我的$con
和session
in和ini文件,因此会话和连接不是问题。
有没有人看到我做错了什么,或者有什么好方法我可以检查看看哪些不起作用?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
编辑:新更新的代码
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
答案 0 :(得分:3)
看起来你正在做很多像这样的事情:
$click_update_stmt->execute(array('$clicks', '$curPage'));
我不确定你在哪里习惯将变量引用为字符串,但你需要放弃它。 '$x'
和$x
是两个截然不同的东西。在第一种情况下,它字面上 '$x'
,在第二种情况下,无论$x
变量恰好代表什么,都是
修复如下:
$click_update_stmt->execute(array($clicks, $curPage));
此外,由于您正在使用准备好的语句,顺便说一句,您不需要也不应该手动转义您的值。将它们应用于bind_param
的占位符是安全的方法。执行任何其他转义会破坏数据。
直接绑定到源:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
不要随意妄想输入htmlspecialchars
这样的内容,或者因为你正在进行货物编程,你在某个地方的YouTube教程中看到了它。该函数仅用于显示值,而不是存储它们。数据库中的数据应尽可能原始。
这段代码存在很多问题,其中一个令我感到困惑的是为什么会出现很多代码。记住SELECT *
,然后将结果绑定到任意变量是麻烦,您的架构可能会更改,然后您的代码不同步。如果这样做,只要有可能将行作为关联数组获取,那么您只需重新命名已删除的列。
最大的问题是它受竞争条件的影响,因为它没有使用原子增量。在编写计数器时,总是将您的更新作为单个语句的操作进行:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
您读取计数,递增计数,然后将其写回数据库的方法意味着如果另一个操作同时运行,您就会引发问题,这很可能是点击计数器代码。