我的表单中包含select
年龄选项和radiobuttons
性别选项。我们的想法是,该表单可用于按年龄和性别搜索特定用户。
目前,表单有时执行header
(见下文),有时不执行。所以假设,我以Conor身份登录,Conor指定他想要搜索年龄在20-21岁之间并且是男性的用户。单击提交后,有时表单会找到某人,有时则不会。我希望查询一直运行,直到找到用户,除非数据库中不存在任何人。
在这种情况下,应该执行标题,将用户带到messages.php
,因为数据库中存在20岁的男性。
这是我的方法:
表格:
<form action="random_chat.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="age_from" id="age_from" value="0"/>
<input type="hidden" name="age_to" id="age_to" value="50"/>
<label for="amount">Age:</label>
from:
<select name="age_from" id="age_a" onchange="checkages_a()">
<option value="none"></option>
<?php
for($i = 17; $i <= 50; ++$i) {
echo "\t", '<option value="', $i. '">', $i, '</option>', "\n";
}
?>
</select>
to:
<select name="age_to" id="age_b" onchange="checkages_b()">
<option value="none"></option>
<?php
for($i = 18; $i <= 50; ++$i) {
echo "\t", '<option value="', $i, '">', $i, '</option>', "\n";
}
?>
</select>
<!-- I have input type submit above the radio buttons due to table layout -->
<input type="submit" class="btn btn-info" name="submit" value="Click to start chat! " />
<label for="amount">Gender:</label>
<input type="radio" name="gender" value="male">Male</input> <br />
<input type="radio" name="gender" value="female">Female</input><br />
<input type="radio" name="gender" value="any">Any</input>
</form>
处理表单的PHP代码:
<?php
$refined_gender = htmlentities (strip_tags(@$_POST['gender']));
$age_from = htmlentities (strip_tags(@$_POST['age_from']));
$age_to = htmlentities (strip_tags(@$_POST['age_to']));
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
if (isset($_POST['submit'])){
// if age parameter used...
$defined_chat = mysqli_prepare ($connect, "SELECT * FROM users WHERE gender =? AND age BETWEEN ? AND ? ORDER BY RAND() LIMIT 1");
mysqli_stmt_bind_param($defined_chat, "sss", $refined_gender, $age_from, $age_to);
mysqli_stmt_execute ($defined_chat);
while ($get_user = mysqli_fetch_assoc($defined_chat)){
$rand_name = $get_user['username'];
$acc_type = $get_user['account_type'];
if ($acc_type != "admin" ){
// if the name genereated by db is same as logged in users name, then run query again until name is found.
if ($rand_name == $username){
$defined_chat;
} else {
header ("Location: /messages.php?u=$rand_name");
}
} else {
echo "No user found fitting those requirements.";
}
} // while closed
mysqli_stmt_close($defined_chat);
}
?>
我已尝试将表单操作更改为&#39;#&#39;,认为它可能只是刷新页面,但它没有用。
另外,我怎样才能这样做,即使填充了一个参数,仍然执行搜索?例如,如果我搜索未定义年龄的男性,则会找到男性用户。如果我搜索年龄介于26-31之间且没有定义性别的人,那么仍然执行标题?
修改:
$username
是会话变量,它在random_chat.php
的最开始定义。
答案 0 :(得分:1)
不要依赖提交按钮的值来确定您的表单是否已提交。这不适用于所有浏览器,尤其是较旧的浏览器,这个值并不总是传递回服务器,而是只查看表单中的任何值以验证是否已提交提交,或者通常是否存在$ _POST。 p>
答案 1 :(得分:0)
乍一看,你所参加的活动对我来说比你实际尝试实现它的方式更简单。
正确构建SQL查询可能是这里唯一复杂的事情。
只更改您的查询实际上已经删除了对account_type
的if / else和if / else的需要,以检查当前用户是否与查询的用户相同:
$sql = "SELECT
*
FROM
users
WHERE
gender like ? AND
age BETWEEN ? AND ? AND
# with this condition you do not need to test if the user logged is the queried one
username != ? AND
# and with this one, you do not care about exclude adimn either
account_type != 'admin'
ORDER BY RAND()
LIMIT 1";
$defined_chat = mysqli_prepare (
$connect, $sql
);
mysqli_stmt_bind_param(
$defined_chat,
"ssss",
$refined_gender,
$age_from,
$age_to,
$username
);
然后,即使您没有对性别和年龄进行任何选择也希望能够进行搜索,您可以使用SQL的通配符%
,运算符like
和PHP的三元运算符(您可能已经看到我在上面的查询中将gender =?
更改为gender like ?
。
// Means if gender is different than 'any', it will assign the posted value to the variable, otherwise, it will assign the sql wildcard %
$refined_gender = (htmlentities (strip_tags(@$_POST['gender'])) != 'any' ? htmlentities (strip_tags(@$_POST['gender'])) : '%');
// Means if age is different than 'none', it will assign the posted value to the variable, otherwise, it will assign the lowest possible age, 0
$age_from = (htmlentities (strip_tags(@$_POST['age_from'])) != 'none' ? htmlentities (strip_tags(@$_POST['age_from'])) : '0');
// Means if age is different than 'none', it will assign the posted value to the variable, otherwise, it will assign an age bigger than anyone could attain, 9999
$age_to = (htmlentities (strip_tags(@$_POST['age_to'])) != 'none' ? htmlentities (strip_tags(@$_POST['age_to'])) : '9999');
见ternary operators in PHP doc 并查看MySQL like and wildcard usage
一体化,您的处理PHP脚本可能如下所示:
$refined_gender = (htmlentities (strip_tags(@$_POST['gender'])) != 'any' ? htmlentities (strip_tags(@$_POST['gender'])) : '%');
$age_from = (htmlentities (strip_tags(@$_POST['age_from'])) != 'none' ? htmlentities (strip_tags(@$_POST['age_from'])) : '0');
$age_to = (htmlentities (strip_tags(@$_POST['age_to'])) != 'none' ? htmlentities (strip_tags(@$_POST['age_to'])) : '9999');
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
if (isset($_POST['submit'])){
$sql = "SELECT
*
FROM
users
WHERE
gender like ? AND
age BETWEEN ? AND ? AND
# with this condition you do not need to test if the user logged is the queried one
username != ? AND
# and with this one, you do not care about exclude adimn either
account_type != 'admin'
ORDER BY RAND()
LIMIT 1";
$defined_chat = mysqli_prepare (
$connect, $sql
);
mysqli_stmt_bind_param(
$defined_chat,
"ssss",
$refined_gender,
$age_from,
$age_to,
$username
);
mysqli_stmt_execute ($defined_chat);
while ($get_user = mysqli_fetch_assoc($defined_chat)){
$rand_name = $get_user['username'];
header ("Location: /messages.php?u=$rand_name");
} // while closed
echo "No user found fitting those requirements.";
mysqli_stmt_close($defined_chat);
}
答案 2 :(得分:0)
你有一些混合逻辑,所以一些解释可能会有所帮助。
1)header('location:...')将告诉浏览器将页面重新加载到新位置。这似乎不是你想要的 - 你只想继续执行?注意:你也应该[几乎]总是有“exit();”标题后面('location:...');否则执行继续,这几乎不是你想要的!)
2)while循环将继续“while”条件为真。因此,当返回行时,循环继续。
3)再次运行查询不会返回任何新内容 - 您可以使用相同的结果。所以请跳过,直到找到所需的结果!
因此,用英文编写,运行数据库查询后要执行的操作是:
set a tally count to zero
while we have some rows coming from the db {
if that row is not admin {
if that row does not match the current user {
show the result
increase tally count
}
}
}
if tally count is zero {
say "no entries found"
}
所以,在代码中,这是
$foundUsers = 0;
while ($get_user = mysqli_fetch_assoc($defined_chat)){
$rand_name = $get_user['username'];
$acc_type = $get_user['account_type'];
if ($acc_type !== "admin" ){
// if the name genereated by db is same as logged in users name, then run query again until name is found.
if ($rand_name !== $username) {
$foundUsers = $foundUsers + 1; // Or $foundUsers++ for short
echo 'Matched User: ' . $rand_name . '<br>';
}
}
} // while closed
if ($foundUsers == 0) {
echo "No user found fitting those requirements.";
}
答案 3 :(得分:0)
好的,首先,如果要从查询中排除参数,您将需要构建一些逻辑来排除该变量。
因此,如果$refined_gender = "any"
,则需要将其从查询中排除。我会将你的组合框默认值更改为:
<select name="age_from" id="age_a" onchange="checkages_a()">
<option value="-1"></option>
<?php
for($i = 17; $i <= 50; ++$i) {
echo "\t", '<option value="', $i. '">', $i, '</option>', "\n";
}
?>
</select>
to:
<select name="age_to" id="age_b" onchange="checkages_b()">
<option value="999"></option>
<?php
for($i = 18; $i <= 50; ++$i) {
echo "\t", '<option value="', $i, '">', $i, '</option>', "\n";
}
?>
</select>
然后,现在您已经修复了年龄,以过滤掉性别。另外,我在您的WHERE
子句中添加了一个子句:AND account_type != 'admin'
,这将过滤掉SQL端的管理员帐户,而不是检查PHP端。
// If gender is specified, query gender
if($refined_gender !== "any"){
$defined_chat = mysqli_prepare ($connect, "SELECT * FROM users WHERE gender =? AND age BETWEEN ? AND ? AND account_type != 'admin' ORDER BY RAND() LIMIT 1");
mysqli_stmt_bind_param($defined_chat, "sii", $refined_gender, $age_from, $age_to);
} else {
$defined_chat = mysqli_prepare ($connect, "SELECT * FROM users WHERE age BETWEEN ? AND ? AND account_type != 'admin' ORDER BY RAND() LIMIT 1");
mysqli_stmt_bind_param($defined_chat, "ii", $age_from, $age_to);
}
mysqli_stmt_execute ($defined_chat);
答案 4 :(得分:0)
建议#1:可能的竞争条件见代码中的注释。
if ($acc_type != "admin" ){
// if the name genereated by db is same as logged in users name, then run query again until name is found.
if ($rand_name == $username){
$defined_chat;<-- don't you need to re-execute this? Seems like you are hitting a race condition since the statement result will never change
} else {
header ("Location: /messages.php?u=$rand_name");
}
} else {
echo "No user found fitting those requirements.";
}
建议#2:
除此之外,你应该确定你没有得到当前用户
在初始查询中预先WHERE name NOT LIKE '%?%'
并删除if语句。
建议#3:
或者更好的是,使用用户ID。如果有另一个用户与搜索者同名,但他们是另一个人怎么办?将当前用户匹配基于UID,而不是名称。
建议#4:
你绝对不应该在PHP(或任何脚本语言)循环中运行select查询/ statment。总有一种更好的方式。在数据库中过滤效率高的数据。即使对于插入,您也可以比一堆插入查询更有效地执行单个批量插入。