PHP How to generate a unique ID equal to the GOOGLE shortener

Asked

Viewed 968 times

1

goo.Gl/A4hi How can I be generating an ID like this from google and check if it already exists, if it succeeds generate another. PHP

  • Please post some more information. What type of ID do you want to generate? How many characters? Only numbers? How do you plan to store this ID?

  • Each time I enter a data in the database it returns the ID generated for example 5, so to access this data is site.com/5 , but I wanted it to be the same as google for example site.com/Hi4jx . But when generating you have to check if the generated characters no longer exist. It has to have a maximum of 5 characters and has to be Case Sensitive

  • 1

    Just use the normal table ID (auto-increment) and convert to base 64. If you want to optimize even more, use a base larger than 64, as long as you respect valid characters in Urls. That is, you do not generate the ID, it already exists. Almost every shortener does this, even the vast majority is sequential, because the predictability of the ID is irrelevant when you don’t know what the content will be.

2 answers

3

There are some things to consider:

  1. It’s interesting that you hide the number?

    If you have /1, /2, /3 a user can change the value and get previous values. This is very bad in some cases, for example on Youtube. Youtube allows hidden videos. If they were sequential a user would have a high probability of finding these videos. In addition to synchronization problems between servers.

    But this is not necessary in all cases.

  2. It’s interesting to use letters?

    You can generate a random number only without converting to letters and symbols. The use of letters and symbols is used because the URL is treated as text.

    Typically, you are able to generate 0 until 18.446.744.073.709.551.615, using only 8 bytes, UINT64. However, if you have a URL of /18446744073709551614, you will use 20 bytes, precisely because each number will be treated as any letter, an individual byte.

    Adding this up, databases would also treat each letter a byte (Suppose you use Base64), being worse to find the data and occupying larger disk space. Therefore, using numbers would be the best option.


My suggestion:

  1. Create a random, unpredictable value (for the attacker).
  2. Encode for Base64 in order to "compress" it to the URL.
  3. When the client accesses the link, decode Base64 to the number value.
  4. Search the database for the numerical value.

To create the URL use:

$int = random_int(PHP_INT_MIN, PHP_INT_MAX);

$base64 = base64_encode(pack('J*', $int)); 
$base64 = rtrim(strtr($base64, '+/', '-_'), '='); 

This code was based on this response. Use the $int to the database, and $base64 to send to the user.

Then, to convert again, use:

$url = 'CODIGO-DO-URL';

$base64 = strtr($url, '-_', '+/');
$base64 = base64_decode($base64);

$int = unpack("J*", $base64)[1];

In this way search the database $int. Of course, this can have worse performance, after all there is a cost for conversion. But, the storage space required will be smaller, this is evident. But, I believe that the database is a bigger problem than the conversion, ie convert the Base64 to int has even greater advantages.


2


I confess I don’t know how to do that automatically. But one solution I thought was you make an associative table between an ID and the generated characters. You would do a function that would generate these 5 characters, check if these characters are already being used, otherwise save the ID and code in the database.

If you want a function to generate these characters I am leaving an example here

function gerarCaracteres($tamanho = 5) {
    $caracteres = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz';
    $retorno = '';
    $len = strlen($caracteres);
    for ($i = 1; $i <= $tamanho; $i++) {
        $rand = mt_rand(1, $len);
        $retorno .= $caracteres[$rand-1];
    }
    return $retorno;
}
  • That’s right, man, vlw

Browser other questions tagged

You are not signed in. Login or sign up in order to post.