Welcome Guest, Not a member yet? Register   Sign In
Generating Unique ID
#1

[eluser]Kemik[/eluser]
Hello,

I'm trying to generate a unique ID for a personal file upload script. I was looking for a 5 character string consisting of alphanumeric characters, both upper and lower.

Is there any way of making it truly unique? E.g. based off the current time or would that be too much hassle? If it isn't possible I was just going to use the below script and do a check in the database to make sure it hasn't already been used.

Code:
function createRandomPassword() {

    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
    srand((double)microtime()*1000000);
    $i = 0;
    $pass = '' ;

    while ($i <= 5) {

        $num = rand() % 33;
        $tmp = substr($chars, $num, 1);
        $pass = $pass . $tmp;
        $i++;

    }
    return $pass;
}
#2

[eluser]Jamie Rumbelow[/eluser]
You could just use time(), to get the unix timestamp, and then sha1 it with a few strings or something. Then use substr to get the 5 char string.

Easy!
#3

[eluser]Michael Wales[/eluser]
You'll never be able to guarantee absolute uniqueness on the insertion by generating a hash and then substringing it. It will be pretty unique - but never guaranteed.

Personally, I would just use the string helper, then loop until the query is properly executed.

Code:
function make_unique($filename = NULL) {
  if ($filename !== NULL) {
    $this->load->helper('string');
    $unique = FALSE;
    while ($unique === FALSE) {
      if ($this->db->update('files', array('id' => random_string('alnum', 5)), array('filename' => $filename))) {
        $unique = TRUE;
      }
    }
    return TRUE;
  }
  return FALSE;
}

Then just set that field as a UNIQUE key within your database engine (or even a primary, since it's the identifier). You don't have to use random_string - hashing time() and then substringing it would work, but you still need a fall-back due to the chance of nonuniqueness.
#4

[eluser]Kemik[/eluser]
Thanks guys. I went with Mike's method.


EDIT: fixed with routing. Don't need to read below.

Final question: I originally wanted to have the string as follows http://www.domain.com/string. If uri 1 is empty (i.e. no string is there) then it displays the regular upload file page. If uri 1 contains a string then the user is shown the file. This was a bit of a pain so I made a new controller for viewing files.

Controllers
- file (index controller) - handles uploads
- v - handles displaying the files.

Now I'm having issues displaying the file as http://www.domain.com/v/string. It says the page has not been found, yet if I do http://www.domain.com/v/index/string it finds the file perfectly.

Any ideas?

EDIT: fixed with routing.
#5

[eluser]Randy Casburn[/eluser]
Rather than write all this stuff yourself, you could rely on what is already written for you. While the php function produces a string 13 characters long by default, it works and you could pull from it what you need. Here it is without any fancy foot work:

Code:
$unique =uniqid();

A better randomization would be:
Code:
$moreUnique = md5(uniqid(rand(), true));

That's directly out of the PHP manual. No credit to me.

If you are using MySQL, you could actully SELECT UUID from MySQL to get a standard UUID as well without any coding other than the query.

No reason to reinvent all this stuff.

Randy
#6

[eluser]Jamie Rumbelow[/eluser]
Ah. Thats because when you do /v/string, Codeigniter is looking for the class v and the function string, not the class v, function index and parameter string.


If you want to keep that url, enter this into your routes.php file:

Code:
$route['v/(.*)'] = "v/index/$1";

Hope i helped!
#7

[eluser]Michael Wales[/eluser]
Quote:While the php function produces a string 13 characters long by default, it works and you could pull from it what you need.
Therefore it doesn't meet his 5 character requirement...
#8

[eluser]Randy Casburn[/eluser]
I know Mike, you being the hero and all, this is sooo much easier:

Code:
function make_unique($filename = NULL) {
  if ($filename !== NULL) {
    $this->load->helper('string');
    $unique = FALSE;
    while ($unique === FALSE) {
      if ($this->db->update('files', array('id' => random_string('alnum', 5)), array('filename' => $filename))) {
        $unique = TRUE;
      }
    }
    return TRUE;
  }
  return FALSE;
}

than this:

Code:
substr(...);

I bow to your prowess...
#9

[eluser]Michael Wales[/eluser]
It was unclear you were referring to looping and checking against the database result to ensure the value was unique. What I thought you meant was:

Code:
$moreUnique = md5(uniqid(rand(), true));
$this->db->insert('table', array('code' => substr($moreUnique, 5)));

Which, simply wouldn't work - for very apparent reasons. In case you aren't catching on:

uniqid() will generate a random, unique, 13-character string. See that? 13 characters...

Let's simplify things a bit, so we're all following along.

mike_uniqid() will generate a unique string that is 3 characters long, digits only. So, we run it and get 014. Now, we substring that down to 2 characters and we have 01.

What happens when we insert that into the database and the next guy comes along and receives 018 for his random string. DING DING DING! The database tries to insert 01, the app pukes, and fail whale gives you a sweet little visit.

Now, back to your recommendation:
uniqid() - no matter how many times you feel like hashing, seeding, etc. generates a random string. Let's say it's: u0sduf0duf9832jhewhj0fjew9f7ud

We substring it down to u0sdu and insert.

Now, fail whale decides to visit our little web app and he gets the random string: u0sduf003kz832jh93hj0fjewlsnud

We substring it... and well, I guess you can see where I am going with this.

So, the conclusion of today's lesson folks:
1. Yes, Randy's solution is better because it doesn't include the loading of a library.
2. You would still have to combine it with the while() loop I explained to ensure a random string is actually being entered into the database.
3. Randy's a smartass and I hope I never have to clean up one of his apps, especially if he thinks a substring of a unique string will result in a unique string.
#10

[eluser]Randy Casburn[/eluser]
OK...I'll admit the characterization was a close match... :roll:
Quote:3. Randy’s a smartass...

But this nice person (Kemik) might benefit from something other than personal insults...

Most of the use cases presented in these forums become less important than what is presented. Especially when multiple options are presented. Having folks explore different options often times explores flaws in designs they realize they've made along the way too.

Kemik might benefit from knowing some time in the future that PHP has already created a randomized string for his upload. If he was to flex a little with his requirement for the format, PHP has already solved his problem without any effort on his part.

If he is truly testing for unique values in a MySQL table, then IMHO MySQL routines are the fastest, most efficient, and most well built for the job.

If you want to continue your insults, please comment on my posts here: http://ellislab.com/forums/viewthread/83797/

In the mean time please accept my apology for being a little over the top in my previous post.

Randy




Theme © iAndrew 2016 - Forum software by © MyBB