2014-11-20 202 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); 
    } 

}