Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

How to create unqiue random string of length n(PHP)

Options
  • 13-02-2010 3:31am
    #1
    Registered Users Posts: 2,234 ✭✭✭


    Hi,

    So I want to create short url id's like bit.ly and tinyurl.com etc.

    Just wondering how do they do it or how I could go about it in PHP.

    I'm thinking that using PHP to generate something random is fine but testing each time fir uniqeness against DB would be expensive.

    My current solution is as follows:

    - Create DB table with 1 column that holds the unique string. table=ID,col=str.
    - each time I need a random/unique id in my PHP app I use "SELECT str FROM ID LIMIT 1". then "DELETE FROM ID WHERE str=$retrieved_value".

    Problem, how to I maintain the id table etc?? Do I need to monitor it to make sure I don't run out etc. Also, could storing all the id's be inefficient?

    I have a feeling this is where database functions will come in? Actually I just found something about UUID() on Google but since I've written this much i'll see what ideas I get..

    Thanks..


Comments

  • Registered Users Posts: 6,509 ✭✭✭daymobrew


    I used base64_encode to create unique urls but this makes them really long (33% longer than the original data), so that's not good for you.

    I wonder would gzencode help?

    IIRC there was an article on sitepoint.com that showed you how to make short urls but I cannot find it. I think it was something as simple as converting an integer e.g. dechex.

    Maybe you could simply insert a new row into the db table (it would have 2 cols - ID (auto increment int) and url (varchar)). Then retrieve the ID of the row and sprintf this number (converted to hex) and pad the string with zeros.

    Obviously this means you are only using 16 chars instead of 36 (the full alphabet and numbers).


  • Registered Users Posts: 354 ✭✭AndrewMc


    I'd second daymobrew's suggestion of using the autoincrement field to give you a unique, new number. If you want you could shorten the outputted value by converting it from base 10 to base 36 (10 digits + 26 letters) using something like:
    base_convert ($number, 10, 36)
    


  • Registered Users Posts: 885 ✭✭✭clearz


    AndrewMc wrote: »
    I'd second daymobrew's suggestion of using the autoincrement field to give you a unique, new number. If you want you could shorten the outputted value by converting it from base 10 to base 36 (10 digits + 26 letters) using something like:
    base_convert ($number, 10, 36)
    


    Yeah I'd change it to base 62 - 10 digits + 26 uppercase + 26 lowercase letters


  • Registered Users Posts: 6,509 ✭✭✭daymobrew


    clearz wrote: »
    Yeah I'd change it to base 62 - 10 digits + 26 uppercase + 26 lowercase letters
    Unfortunately the max appears to be 36 according to the base_convert docs.
    [php]
    for ($i=0; $i <100; $i+=rand(1,9)) {
    echo "$i = ", base_convert($i, 10, 36), "\n";
    }
    [/php]
    produces:
    0 = 0
    3 = 3
    4 = 4
    6 = 6
    8 = 8
    11 = b
    18 = i
    21 = l
    25 = p
    32 = w
    36 = 10
    43 = 17
    46 = 1a
    48 = 1c
    51 = 1f
    57 = 1l
    63 = 1r
    71 = 1z
    75 = 23
    78 = 26
    85 = 2d
    86 = 2e
    93 = 2l
    99 = 2r
    

    PS. You don't need to pad the strings with zeros - tinyurl started at 1 e.g. http://tinyurl.com/2 works! ('1' is marked as spam).


  • Registered Users Posts: 2,234 ✭✭✭techguy


    Thanks for the replies guys..

    I must (shamefully) admit that i'm kind of lost with your replies. I must read up on base_convert.

    What i'm trying to do is generate a unique 5 character id for each user upon registration. I forgot to mention earlier that the first letter must always be uppercase.

    Here's something I just threw together:
    [PHP]
    $uid = 1;
    $url = base_convert ($uid, 10, 36);

    while (strlen($url)<5)
    {
    $url .= chr(rand(65,90));
    }
    [/PHP]

    $uid is the users unique (DB pri key & auto inc). Base_convert does its magic to generate the url_id. The loop just pads out the string with random characters until I get the desired string length (5).

    The loop can be configured to set the min length required for the url id. Once the auto incremented user id has reached a level this loop is just bypassed. Then convert to uppercase to ensure first character is uppercase.

    The reason for the first letter being uppercase is that CodeIgniter can determine that a short url has been sent and not just a normal url.

    What do ye think?


  • Advertisement
  • Registered Users Posts: 354 ✭✭AndrewMc


    The problem with padding with random characters is you can't tell the difference between the "significant" part and the padding. Given ABCDE as input, is A the code and BCDE the padding, or AB the code and CDE the padding, etc? Your best bet is to left-pad with zeros: 00001, 00002, 00003, ... — no ambiguity there, always drop the leading zeros.


  • Registered Users Posts: 2,234 ✭✭✭techguy


    AndrewMc wrote: »
    The problem with padding with random characters is you can't tell the difference between the "significant" part and the padding. Given ABCDE as input, is A the code and BCDE the padding, or AB the code and CDE the padding, etc? Your best bet is to left-pad with zeros: 00001, 00002, 00003, ... — no ambiguity there, always drop the leading zeros.

    Everything will be relevant.. This string will be generated on registration of a new user then stored in the DB with that users record.

    Then the url: domain.com/IOJSD is entered the program will know what user is requested by using "IOJSD" to lookup the database.


  • Registered Users Posts: 2,781 ✭✭✭amen


    not a php head but you want a 5 character unique id ? when you say characters I assume you mean a-z and A-Z (not sure why you are not using numeric)

    so how about just generate5 random numbers between the ascii of A (ascii 65) and z(122)

    convert back to numeric and away you go ? (you could check to see if it already exists in database)


  • Subscribers Posts: 9,716 ✭✭✭CuLT


    I wrote a blog post a while back that might help - a base 56 integer conversion function in PHP.


  • Moderators, Recreation & Hobbies Moderators, Science, Health & Environment Moderators, Technology & Internet Moderators Posts: 91,732 Mod ✭✭✭✭Capt'n Midnight


    you could use something like MD5 checksum - fairly unlikely to get duplicate URL's so you could ignore checks (LOL) - one way hash's makes for laziness, but hey



    URL's are not case sensitive a=A etc.
    Unicode URL's are now valid too
    URL's can contain . - _ etc. so more than 36 characters


  • Advertisement
Advertisement