Question

For my domain, I'm trying to develop an ID generator that creates a unique ID, which can then be used for a shortlink (just as a URL shortener does).

I thought about using md5() or uniqueid() to create that ID. But to keep URLs as short as possible, this wouldn't be smart, as it passes out a huge amount of IDs, so the string/ID would get longer without any necessity.

Now PHP's string incrementation offers an interesting way. I could do:

$d = 'A08';
for ($n=0; $n<60; $n++) {
    echo ++$d . PHP_EOL;
}
// Outputs: A09 .. A68

But this only gives me all strings from A09 to A68. So I set $d = '000' in order to start from there. But now it only returns integers from 1 to60, instead of strings.

How can I force PHP to increment from 000 via AAA to ZZZ?

So to speak, I want an id than runs from 0 via 9 via A to Z and a to z.

0, 1, 2, .., 9, A, .., Z, a, .., z

Then the second character shall be added to the id:

00, 01, 02, .., 09, 0A, .., 0Z, 0a, .., 0z
Was it helpful?

Solution

I've done something similar to this on http://filepublicator.com. My solution was that each post gets its own unique incremental id (just like you normally would give them: 1, 2, 3, etc..), and also a copy of this id converted to base 62.

Then I use this base 62 copy as the url. Heres another thread on SO about this: converting a number base 10 to base 62 (a-zA-Z0-9)

I went with this method of first generating a real id and then converting it to base 62 because then I know I have a unique id without testing it against my already existing posts and it can easily be translated to my real id on the fly.

Theoretically someone could easily figure out my method of creating urls and try to loop through all my pages, but if you are looking for making posts hidden and hard to find short urls without password protection isen't the way to go.

This is the method written by Eineki in that thread:

function toBase($num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $r = $num  % $b ;
  $res = $base[$r];
  $q = floor($num/$b);
  while ($q) {
    $r = $q % $b;
    $q =floor($q/$b);
    $res = $base[$r].$res;
  }
  return $res;
}

function to10( $num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $limit = strlen($num);
  $res=strpos($base,$num[0]);
  for($i=1;$i<$limit;$i++) {
    $res = $b * $res + strpos($base,$num[$i]);
  }
  return $res;
}

The test

for ($i = 0; $i<1000000; $i++) {
  $x =  toBase($i);
  $y =  to10($x);
  if ($i-$y)
    echo "\n$i -> $x -> $y";
}

OTHER TIPS

You could generate AAA - ZZZ as follows:

for($key = 'AAA'; $key != 'ZZZ'; $key++) {
    echo $key;
}

Hopefully I understood your question correctly.

Edit:

$last_key = 'ZZZ';
for($key = 1; $key != $last_key; $key++) {
    echo is_int($key) ? sprintf('%03d', $key) : $key;
    if($key == 999) { $key = 'AAA'; }
}

Output:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
...
...
998
999

Followed by

AAB
AAC
AAD
AAE
AAF
AAG
AAH
AAI
AAJ
AAK
AAL
AAM
AAN
AAO
AAP
AAQ
AAR
AAS
AAT
AAU
...
...
ZZX
ZZY

This returns results "a01" - "cw00"

<?php
   $d = 'a00';
   for ($n=0; $n < 10000; $n++) {
    echo ++$d . PHP_EOL;
   }
?>

Not quite sure if this is what you are looking for...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top