【问题标题】:create new if already exists PHP如果已经存在,则创建新的 PHP
【发布时间】:2012-12-14 14:26:30
【问题描述】:

我正在创建一个随机用户 ID,但我想检查该 ID 是否已被使用(不太可能,但有机会),但不知何故这不起作用。当我查看数据库时,account_id 字段中没有随机字符串。我是否以错误的方式调用函数?

function genRandomString() {
    $length = 40;
    $characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";    
    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters))];
    }
    return $string;
}

function createID() {
    $cl_id = 'h_u_'.genRandomString();
}   

createID();

$sql_query="SELECT * FROM accounts WHERE account_id = :cl_id";
$statement = $conn->prepare($sql_query);
$statement->bindParam(':cl_id', $cl_id, PDO::PARAM_STR);    
if ($statement->execute() && $row = $statement->fetch())
    {
        createID();
    }

$conn->exec("INSERT INTO accounts SET  
            account_id='$cl_id' ,
            name='$_POST[name]' ,
            email='$_POST[email]' ");   

【问题讨论】:

  • 您没有自动增量列吗?那会减少检查ID是否存在的痛苦吗?因为自动递增的列只会通过递增的数字自动填充您的 ID 列并确保没有行是完全相同的
  • 他可以将 id 列作为主键并将他的 user_id 添加为 varchar(10) 或其他内容作为唯一索引 ...
  • 在许多方面将主键作为字符串并不是很有效。另外,您的代码不保证该列将是唯一的(假设您在该列上也设置了此约束)。为什么没有 AUTO_INCREMENT PK,如果您真的 需要一些唯一标识符字符串,只需从用户 ID(PK 自动增量)和电子邮件生成一个 (sha1)。无论如何,两者首先都应该是独一无二的......

标签: php function insert pdo user-registration


【解决方案1】:

$cl_id 是 createID() 函数中的一个局部变量,你需要将你的值返回给你的全局代码...

function createID() {
return $cl_id = 'h_u_'.genRandomString();
}   

你需要检查主代码中的$id

$id = createID();
$sql_query="SELECT * FROM accounts WHERE account_id = '".$cl_id."'";
$statement = $conn->prepare($sql_query);

【讨论】:

  • 那么绑定params的目的是什么?
  • 没问题,请考虑其他用户的反馈,以防它可以改进您的项目或应用程序...祝您有美好的一天
【解决方案2】:

1 .您错过了在 createID() 中返回 $c_id。将其更改为:

function createID() {
    return 'h_u_'.genRandomString();
}

$cl_id = createID();

2 。您可以使用旧的uniqid() 而不是您的自定义genRandomString()

这会导致一些更简单的事情,例如:

function createID() {
    return 'h_u_'.uniqid();
}

$cl_id = createID();

3 .您必须将数据库相关代码中的 if 更改为循环(请看下面的示例)

4 。您的插入查询使用未经验证的 $_POST 变量。这很容易出现SQL Injections。如果您的数据库库支持服务器端准备好的语句,您应该使用它们并且您会感到安全,因为数据与查询语法是分开的。如果您将 PHP 与 MySQL 一起使用,情况就是如此。

如果您没有使用 服务器端 准备好的语句,您应该使用 mysql_real_escape_string() 或类似的东西来转义查询中使用的任何 $_POST 数据。在下面的示例中,我假设您将 PHP 与 MySQL 一起使用,这就是我使用准备好的语句的原因。

考虑到所有这些可能会导致完成的脚本如下:

$sql_query="SELECT * FROM accounts WHERE account_id = :cl_id";
$statement = $conn->prepare($sql_query);
$maxtries = 3; // how many tries to generate a unique id?

for($i = 0; $i < $maxtries; $i++) {
    $cl_id = uniqid(); // create a 'unique' id

    $statement->bindParam(':cl_id', $cl_id, PDO::PARAM_STR);    
    if (!$statement->execute()) {
        die('db error');
    }

    $row = $statement->fetch();
    if($row) {
        continue;
    }
    break;
}

// if a unique id couldn't get generated even
// after maxtries, then pigs can fly too :)
if($i === $maxtries) {
    die('maximum number of tries reached. pigs can fly!');
}

// You should use a prepared statement for the insert to prevent from
// SQL injections as you pass $_POST vars to the query. You should further 
// consider to validate email address and the name!
$name = $_POST['name'];
$email = $_POST['email'];

$insert_query = '
  INSERT INTO accounts SET 
    account_id = :account_id,
    name = :name,
    email = :email'; 

$insert_statement = $conn->prepare($insert_query);
$insert_statement->bindParam(':account_id', $cl_id, PDO::PARAM_STR);
$insert_statement->bindParam(':name', $name, PDO::PARAM_STR);
$insert_statement->bindParam(':account_id', $email, PDO::PARAM_STR);

if (!$insert_statement->execute()) {
    die('db error');
}

【讨论】:

  • 很好的答案,但请不要将 $_POST 变量直接插入 SQL。有人可能会认为你的代码是正确的,但这是一个广泛开放的 SQL 注入漏洞。
  • @Bill Karwin .. 是的,你是对的。大多数与 PHP/MySQL 相关的帖子都容易出现多个漏洞。但是我该怎么办?编写充满安全检查的示例,以便(假设没有经验的)提问者不再理解答案的原则?一次又一次?我不确定..欢迎提出建议! ....
  • 是的,这是一个很好的观点,如果我们要遵循所有编码最佳实践,我们将在源代码控制中跟踪代码并编写单元测试。 :-) 但我认为用 SQL 查询参数替换字符串插值是一个合理的折衷方案。顺便说一句,将值作为数组参数传递给execute() 比编写所有bindParam() 调用更容易。无论如何,PDO 都会忽略 PARAM 类型,至少在 MySQL 驱动程序中是这样。
  • 好的,会为此准备一些sn-ps ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 2014-10-08
相关资源
最近更新 更多