2014-11-20 196 views
4

我想根据名字和姓氏自动生成用户名。例如, 如果firstname = Johnlastname = Tory那么用户名应该是johntory。但是,如果该用户名已经存在于数据库中,我想以1递增,这意味着具有相同的名称,下一个用户名将是johntory2在php中自动生成用户名

我在PHP这样的事情..

foreach($existing_users as $u){ 
    if($u['username'] != $new_generated_username){ 
    // Enter it directly... 
    } 
    else{ 
    // increment count value... 
    } 
} 

但是,有一个问题,如果用户名是像johntory5或东西... 有什么办法,我可以直接INSERT语句中更新在MySQL中检查一切。

这是SQLFiddle

+0

你或许应该立足于一个auto_incremented ID添加的数量(INT)柱,并增加它基于这一点。 *想想outloud * – 2014-11-20 16:57:01

+0

@ Fred-ii-:你的意思是,如果用户名已经存在,那么我需要用当前的自动增量ID联系用户名? – 2014-11-20 16:58:39

+0

准确地说,所有在条件语句中设置。这就是我要做的。 – 2014-11-20 16:59:25

回答

2

您可以轻松地做到这一点,直接在INSERT语句是这样的:

INSERT INTO User (username, first, last) 
SELECT CONCAT('johntory', COUNT(id)), 'John', 'Tory' 
FROM User WHERE username LIKE 'johntory%'; 

或者,如果你不不喜欢前面的零,你可以用这个:

INSERT INTO User (username, first, last) 
SELECT CONCAT('johntory', CASE WHEN COUNT(id) = 0 THEN '' ELSE COUNT(id) END), 'John', 'Tory' 
FROM User WHERE username LIKE 'johntory%'; 

这是非常快速和高效的。它使用子查询来准备值,然后插入它们。另外,这将比这里提供的任何PHP解决方案快很多倍,特别是在处理数十亿行时。

我个人喜欢MySql的简单性和性能

享受!

〜Techdude

+0

我也应该补充说,对于用户名本身,你可以在PHP中转换为小写字符串,并在构建查询时进行连接。 – techdude 2014-11-20 20:29:15

+0

哇。这是一个很好的解决方案。这就是我一直在寻找的。你可以请你添加代码,如何从第一个条目中删除“0”?谢谢。 – 2014-11-20 21:04:54

+0

完成!请参阅上面的替代版本。 – techdude 2014-11-22 00:22:14

0

您可以尝试生成与第一和姓氏串联的用户名。然后使用MySql中的LIKE子句查找任何匹配的用户名。这将生成一组完全匹配或像自动生成的用户名的用户名。然后,您可以遍历该数组,直到您自动生成数据库中不存在的用户名。

在PHP中看起来像这样。

// The $suffix is the number to add if the username exists. The default is NULL/nothing 
$suffix = null; 

// Auto-generate the username. 
$username = generate_username_function($firstname, $lastname, $suffix); 

// Instantiate a new PDO instance. 
$pdo = new PDO('mysql:host=...', $db_username, $db_password); // Insert your DNS string here. 

// Build the SQL query. 
$query = " 
    SELECT username 
    FROM users 
    WHERE username LIKE ':username%' 
"; 

$statement = $pdo->prepare($query); 

$statement->bindParam(':username', $username, PDO::PARAM_STR); 

if(!$statement->execute()) { 
    // throw an exception if the query couldn't be executed. 
} 

$existing = $statement->fetchAll(PDO::FETCH_ASSOC); 

// Loop through the existing usernames to check if the auto-generated username exists. 
// Set an $available flag on indicate when the username is available. 
$available = false; 

$current = 1; 
$ceiling = 1000; // This is to avoid infinite loops. Increase this if necessary. 

while(!$available) { 

    // Check if the loop ceiling has been reached. 
    if($current == $ceiling) { 
     // throw an exception(preferred) or emit an error. 
    } 

    if(!in_array($username, $existing)) { 

     $available = true; 

    }else{ 

     if(is_null($suffix)) { 
      $suffix = 1; 
     }else{ 
      $suffix++; 
     } 

    $username = generate_username_function($firstname, $lastname, $suffix); 

    } 

    $current++; 
} 

这将继续递增后缀,直到找到可用的用户名。可以改进用户名的生成,但我会将其留给您:D

现在您有一个可用的用户名,您可以将其与任何其他信息一起存储在数据库中。

此致敬礼。

+0

我们不能有无限数据库,那么就没有机会无限循环,没有任何限制....(除MAX_INT检查;)) – 2014-11-20 17:24:43

+0

这是正确的。我只是想象一些疯狂的情况,并决定确定。但你是对的,我亲爱的先生:D – AnotherGuy 2014-11-20 17:26:56

+0

使用'LIKE'这听起来像一个坏主意。只需将用户的实际名称存储在数据库中,然后查询。这可以防止一个缓慢的'LIKE'并且防止不被愚弄的笨蛋。 'PeeHaa' /'PeeHaaNotTheSame'。 – PeeHaa 2014-11-20 17:28:31

2

在PHP中的循环简单的方法:

<? 
$con=mysqli_connect("localhost","user","pass","database"); 

$username = mysqli_real_escape_string($con,'johntory'); 
$tmp = $username; 
$inc = 1; 
$valid = false; 

// lookup if the username is in use 
$qid = mysqli_query($con,"select id from User where username='$username'"); 
if(mysqli_num_rows($qid) == 0) $valid = true; 

// if it is in use, keep looking up until a valid username is found 
while(!$valid) { 
    $username = $tmp . $inc; // append number 
    $qid = mysqli_query($con,"select id from User where username='$username'"); 
    if(mysqli_num_rows($qid) == 0) $valid = true; 
    $inc++; 

    //optional 
    if($inc>1000) die("Too many John Tory's"); 
} 

// insert user 
mysqli_query($con,"insert into User(username) values ('$username')"); 
?> 

你可能想在用户名添加一个索引,以加快查询。

+0

它工作正常。但唯一的问题是,while循环中有一个'query'。性能会随着时间变慢。 – 2014-11-20 19:22:19

+0

是的。如果添加用户名索引并使用PDO准备好的语句,速度会更快。另一个答案可能会更快,你将不得不尝试。我会使用REGEXP而不是LIKE,以防止johntory与johntorydoe发生冲突。例如。 '用户名正则表达式':用户名[0-9] * $'' – 2014-11-20 20:44:12

+0

我认为@ techdude的答案将解决性能问题。它在相同的查询中进行检查。感谢您的支持。 – 2014-11-20 21:06:36

1

我会为用户提供一个表,其中每行保留该用户名的下一个建议编号。

enter image description here

然后用户寄存器功能可以是这样的:

class User { 

    private $firstName; 
    private $lastName; 

    public function __construct($firstName, $lastName) { 
     $this->firstName = $firstName; 
     $this->lastName = $lastName; 
    } 

    public function register(Db $db) { 
     $username = $this->firstName . $this->lastName; 

     $query = "SELECT next_suggestion_id FROM user WHERE username = '$username'"; 
     $rows = $db->execute($query); 

     if (!empty($rows)) { 
      //user found, incrementing next suggestion id 
      $newSuggestionId = $rows[0]['suggestion_id'] + 1; 
      $query = "INSERT INTO user SET suggestion_id = $newSuggestionId" 
         . " WHERE username = '$username'"; 
      $db->execute($query); 

      $username .= $newSuggestionId; 
     } 

     //inserting user in db 
     $query = "INSERT INTO user SET username = '$username' /* other columns */"; 
     $db->execute($query); 
    } 

}