这里的第一个问题,如果我做了一些愚蠢的事情,请不要打扰我!
我正在创建一个包含注册等的登录系统。在注册时我需要测试3件事情,看看他们是否已经在使用。
我的初始测试代码如下所示:
$IDq = $userdbc->query("SELECT * FROM users WHERE userID = '$uID'");
$IDq->setFetchMode(PDO::FETCH_ASSOC);
$IDf = $IDq->fetch();
if($IDf['userID']){
echo '<p>ID exists</p>';
}
else{
echo '<p>ID does not exist?</p>';
}
我将需要测试可能重复的电子邮件和显示名称..我确定必须有更好的方法来解决这个问题吗?
或者我真的要重复这个过程3次以测试每个项目吗?
这是我第一次使用数据库解决方案的真正冒险..非常感谢任何有用的输入 - 提前感谢!
编辑:我确实需要单独测试每个值,以便我可以使用适当的错误消息重建注册表单,说明确切需要更改的内容。对不起,我应该更具体。
编辑:解决方案 - 谢谢Shakti Singh,以及其他所有人的帮助。
该函数(使用带有命名占位符的预准备语句):
function item_exists($dbc, $col, $val){
$query = $dbc->prepare("SELECT * FROM users WHERE $col = :val");
$query->execute(array(':val' => $val));
$fetch = $query->fetch();
if($fetch[$col]){
return true;
}
else{
return false;
}
}
我如何在我的注册验证功能中使用它:
$userdbc = new PDO('sqlite:db/users.s3');
if(item_exists($userdbc, 'userID', $_POST['id'])){
$valid = false;
array_push($sub['e'], 'User ID is not available.');
}
if(item_exists($userdbc, 'userEmail', $_POST['email'])){
$valid = false;
array_push($sub['e'], 'Email Address is already in use.');
}
if(item_exists($userdbc, 'userName', $_POST['name'])){
$valid = false;
array_push($sub['e'], 'Display Name already taken.');
}
$userdbc = null;
编辑:其他:
因为我只测试了一个项目,所以我替换了item_exists()
函数:
$query->execute(array(':val' => $val));
有:
$query->bindParam(':val', $val);
$query->execute();
..只是因为执行一个数组对我来说似乎有些愚蠢,因为它只有一个键/值..
不知道实际差异可能是什么,但嘿,这是另一种选择。
编辑:附加 - 附加:
所有更改的功能:
function item_exists($dbc, $col, $val, $rn){
// updated the prepare statement as per James Anderson's suggestion.
$query = $dbc->prepare("SELECT COUNT($col) AS dupli FROM users WHERE $col = :val");
$query->bindParam(':val', $val);
$query->execute();
$fetch = $query->fetch();
// $fetch['dupli'] contains the number of matches found.
// $fetch[0] should also work, but not tested.
if($rn){ // if $rn = true, return the number of finds
return $fetch['dupli'];
}
else{ // else we are just testing for a match so..
if($fetch['dupli'] > 0){ // if we have one
return true;
}
else{
return false;
}
}
}
我觉得我应该加上这个以防万一其他人像我一样挣扎,总是很高兴有工作的例子 - 也有评论^ _~
我很确定这将是我的最后一次编辑,但是......永远不会知道。
答案 0 :(得分:2)
不要重复此过程3次以测试每个项目。
只需创建一个通用方法或函数,将为要检查的每个项调用该函数,并根据数据库值返回true或false。
function item_exists($item_value,$item_type)
{
$IDq = $userdbc->query("SELECT * FROM users WHERE $item_type= '$item_value'");
$IDq->setFetchMode(PDO::FETCH_ASSOC);
$IDf = $IDq->fetch();
if($IDf[$item_type])
{
return true;
}
else
{
return false;
}
}
并像这样调用函数
if (item_exists($userID, 'userID') === true)
{
echo 'user_id exists';
}
if (item_exists($emailID, 'email') === true)
{
echo 'email exists';
}
此方法可让您知道重复的内容。这样您就可以向最终用户显示消息。
答案 1 :(得分:1)
它们是三个不同的测试,为什么不是三个SQL?
您可以而且应该将“select *
”更改为“select count(*) as idcount
”,因为只有索引访问才能满足整个查询。
如果您真的想在一个SQL中执行此操作,那么:
Select sum(DUP_USER) as du, sum(DUP_NAME) as dn, Sum(DUP_EMAIL) as de
from (
Select Case when userId = '$Uid' then 1 Else 0 End AS DUP_USER
Case when userName = '$uname' then 1 Else 0 End AS DUP_NAME
Case when userEmail = '$uEmail' then 1 Else 0 End as DUP_EMAIL
From users
WHERE userID= '$uID'
OR userName = '$uName'
OR userEmail = '$uEmail' )
但老实说,三个单独的SQL更具可读性。
答案 2 :(得分:0)
只需在WHERE
子句中添加条件(如
WHERE userID= '$uID' OR userName = '$uName' OR userEmail = '$uEmail'
所以当这样做时,如果任何一个条件满足,那么你会得到一行,然后你就会知道存在重复的条目
修改强>
有关OR的进一步阅读 - 请在主题或优化
下查看The SQLite Query Planner答案 3 :(得分:0)
您始终可以使用OR语句:
$IDq = $userdbc->query("SELECT * FROM users WHERE userID = '$uID' OR email='$email' OR displayName='$displayName'");
$IDq->setFetchMode(PDO::FETCH_ASSOC);
$IDf = $IDq->fetch();
echo ($IDf['userID'] == $uID) ? '<p>ID exists</p>' : '<p>ID does not exist?</p>';
echo ($IDf['email'] == $email) ? '<p>Email exists</p>' : '<p>Email does not exist?</p>';
echo ($IDf['displayName'] == $displayName) ? '<p>DisplayName exists</p>' : '<p>DisplayName does not exist?</p>';
我希望您在将这些值发送到数据库之前逃避这些值,并且在您的帖子中错过了该部分。否则你会接受SQL注入