web-dev-qa-db-fra.com

Comment puis-je créer de courtes clés uniques aléatoires, comme des identifiants de vidéo YouTube, en PHP?

Existe-t-il un moyen de créer des clés uniques comme celles utilisées dans les URL des vidéos YouTube (ex: https://www.youtube.com/watch?v=nWChTnkVdKE )?

39
kusanagi

L'idée est de convertir un entier unique (comme l'heure actuelle) dans une autre base mathématique.

Une manière très simple dans PHP:

// With this precision (microsecond) ID will looks like '2di2adajgq6h'

$id = base_convert(microtime(false), 10, 36);


// With less precision (second) ID will looks like 'niu7pj'

$id = base_convert(time(), 10, 36);
35
Diantre

Une petite classe PHP pour générer des hachages de type YouTube à partir d'un ou plusieurs nombres. Utilisez des hachages lorsque vous ne souhaitez pas exposer vos identifiants de base de données à l'utilisateur.

Source: https://github.com/ivanakimov/hashids.php

7
Junaid Atari

Utilisez celui que vous aimez :-)

// Génère une sortie alphanumérique

function generateRandomID() {
    // http://mohnish.in
    $required_length = 11;
    $limit_one = Rand();
    $limit_two = Rand();
    $randomID = substr(uniqid(sha1(crypt(md5(Rand(min($limit_one, $limit_two), max($limit_one, $limit_two)))))), 0, $required_length);
    return $randomID;
}

// Génère uniquement une sortie alphabétique

function anotherRandomIDGenerator() {
    // Copyright: http://snippets.dzone.com/posts/show/3123
    $len = 8;
    $base='ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz';
    $max=strlen($base)-1;
    $activatecode='';
    mt_srand((double)microtime()*1000000);
    while (strlen($activatecode)<$len+1)
    $activatecode.=$base{mt_Rand(0,$max)};
    return $activatecode;
}
5
MT.

Voir le blog de Sean Coates:

Je voulais que le raccourcisseur d'URL crée les URL les plus courtes possibles. Pour garder le nombre de caractères dans une URL court, j'ai dû augmenter le jeu de caractères pouvant comprendre une clé.

et aussi l'article lié dans:

Sur un sidenote, cela a probablement été répondu auparavant

5
Gordon

Voici une petite fonction qui génère une clé unique au hasard à chaque fois. Il a très peu de chances de répéter le même identifiant unique.

function uniqueKey($limit = 10) {

    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    $randstring = '';

    for ($i = 0; $i < $limit; $i++) {

        $randstring .= $characters[Rand(0, strlen($characters))];
    }

    return $randstring;
}

source: http://guruquest.net/question/how-to-generate-random-unique-ids-like-youtube-or-tinyurl-in-php/

4
Bhaskar Bhatt

Pour moi, le meilleur algorithme est le suivant: Créer des identifiants de type Youtube avec PHP/Python/Javascript/Java/SQL

<?php
/**
 * Translates a number to a short alhanumeric version
 *
 * Translated any number up to 9007199254740992
 * to a shorter version in letters e.g.:
 * 9007199254740989 --> PpQXn7COf
 *
 * specifiying the second argument true, it will
 * translate back e.g.:
 * PpQXn7COf --> 9007199254740989
 *
 * this function is based on any2dec && dec2any by
 * fragmer[at]mail[dot]ru
 * see: http://nl3.php.net/manual/en/function.base-convert.php#52450
 *
 * If you want the alphaID to be at least 3 letter long, use the
 * $pad_up = 3 argument
 *
 * In most cases this is better than totally random ID generators
 * because this can easily avoid duplicate ID's.
 * For example if you correlate the alpha ID to an auto incrementing ID
 * in your database, you're done.
 *
 * The reverse is done because it makes it slightly more cryptic,
 * but it also makes it easier to spread lots of IDs in different
 * directories on your filesystem. Example:
 * $part1 = substr($alpha_id,0,1);
 * $part2 = substr($alpha_id,1,1);
 * $part3 = substr($alpha_id,2,strlen($alpha_id));
 * $destindir = "/".$part1."/".$part2."/".$part3;
 * // by reversing, directories are more evenly spread out. The
 * // first 26 directories already occupy 26 main levels
 *
 * more info on limitation:
 * - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/Ruby/ruby-talk/165372
 *
 * if you really need this for bigger numbers you probably have to look
 * at things like: http://theserverpages.com/php/manual/en/ref.bc.php
 * or: http://theserverpages.com/php/manual/en/ref.gmp.php
 * but I haven't really dugg into this. If you have more info on those
 * matters feel free to leave a comment.
 *
 * The following code block can be utilized by PEAR's Testing_DocTest
 * <code>
 * // Input //
 * $number_in = 2188847690240;
 * $alpha_in  = "SpQXn7Cb";
 *
 * // Execute //
 * $alpha_out  = alphaID($number_in, false, 8);
 * $number_out = alphaID($alpha_in, true, 8);
 *
 * if ($number_in != $number_out) {
 *   echo "Conversion failure, ".$alpha_in." returns ".$number_out." instead of the ";
 *   echo "desired: ".$number_in."\n";
 * }
 * if ($alpha_in != $alpha_out) {
 *   echo "Conversion failure, ".$number_in." returns ".$alpha_out." instead of the ";
 *   echo "desired: ".$alpha_in."\n";
 * }
 *
 * // Show //
 * echo $number_out." => ".$alpha_out."\n";
 * echo $alpha_in." => ".$number_out."\n";
 * echo alphaID(238328, false)." => ".alphaID(alphaID(238328, false), true)."\n";
 *
 * // expects:
 * // 2188847690240 => SpQXn7Cb
 * // SpQXn7Cb => 2188847690240
 * // aaab => 238328
 *
 * </code>
 *
 * @author  Kevin van Zonneveld &lt;[email protected]>
 * @author  Simon Franz
 * @author  Deadfish
 * @author  SK83RJOSH
 * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
 * @version   SVN: Release: $Id: alphaID.inc.php 344 2009-06-10 17:43:59Z kevin $
 * @link    http://kevin.vanzonneveld.net/
 *
 * @param mixed   $in   String or long input to translate
 * @param boolean $to_num  Reverses translation when true
 * @param mixed   $pad_up  Number or boolean padds the result up to a specified length
 * @param string  $pass_key Supplying a password makes it harder to calculate the original ID
 *
 * @return mixed string or long
 */
function alphaID($in, $to_num = false, $pad_up = false, $pass_key = null)
{
  $out   =   '';
  $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $base  = strlen($index);

  if ($pass_key !== null) {
    // Although this function's purpose is to just make the
    // ID short - and not so much secure,
    // with this patch by Simon Franz (http://blog.snaky.org/)
    // you can optionally supply a password to make it harder
    // to calculate the corresponding numeric ID

    for ($n = 0; $n < strlen($index); $n++) {
      $i[] = substr($index, $n, 1);
    }

    $pass_hash = hash('sha256',$pass_key);
    $pass_hash = (strlen($pass_hash) < strlen($index) ? hash('sha512', $pass_key) : $pass_hash);

    for ($n = 0; $n < strlen($index); $n++) {
      $p[] =  substr($pass_hash, $n, 1);
    }

    array_multisort($p, SORT_DESC, $i);
    $index = implode($i);
  }

  if ($to_num) {
    // Digital number  <<--  alphabet letter code
    $len = strlen($in) - 1;

    for ($t = $len; $t >= 0; $t--) {
      $bcp = bcpow($base, $len - $t);
      $out = $out + strpos($index, substr($in, $t, 1)) * $bcp;
    }

    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $out -= pow($base, $pad_up);
      }
    }
  } else {
    // Digital number  -->>  alphabet letter code
    if (is_numeric($pad_up)) {
      $pad_up--;

      if ($pad_up > 0) {
        $in += pow($base, $pad_up);
      }
    }

    for ($t = ($in != 0 ? floor(log($in, $base)) : 0); $t >= 0; $t--) {
      $bcp = bcpow($base, $t);
      $a   = floor($in / $bcp) % $base;
      $out = $out . substr($index, $a, 1);
      $in  = $in - ($a * $bcp);
    }
  }

  return $out;
}
1

D'après les commentaires sur ici :

<?php 
function generateRandStr($length){ 
      $randstr = ""; 
      for($i=0; $i<$length; $i++){ 
         $randnum = mt_Rand(0,61); 
         if($randnum < 10){ 
            $randstr .= chr($randnum+48); 
         }else if($randnum < 36){ 
            $randstr .= chr($randnum+55); 
         }else{ 
            $randstr .= chr($randnum+61); 
         } 
      } 
      return $randstr; 
   } 
?> 

Simply use: 
generateRandStr(10); 

Sample output: $%29zon(4f

Vous pouvez jouer avec cette fonction pour générer uniquement des caractères alphanumériques ou alphabétiques.

1
Chetan

Dans la plupart des cas uniqid suffira, si vous devez vous assurer qu'il n'y a absolument aucun conflit, des mesures plus compliquées sont nécessaires.

1
Wrikken
<?php
function keygen(){
    $chars = "bcdfghjklmnpqrstvwxyz";
    $chars .= "BCDFGHJKLMNPQRSTVWXYZ";
    $chars .= "0123456789";
    while(1){
        $key = '';
        srand((double)microtime()*1000000);
        for($i = 0; $i < 10; $i++){
            $key .= substr($chars,(Rand()%(strlen($chars))), 1);
        }
        break;
    }
    return $key;
}

//echo keygen();
?>
1
madhushankarox

Je cherchais une solution très rapide et simple (qui n'était PAS destinée à être sécurisée de quelque manière que ce soit) qui reproduirait le code de hachage réel lors de la régénération (contrairement à l'identifiant unique microtime de PHP). Celui-ci a fait l'affaire.

http://php.net/manual/en/book.hash.php

Alors:

for($i=0;$i<count($myArray);$i++) {
    $hashCode = "#".hash('crc32b', $myArray[$i]."-".$i);        
}

Rendements:

#179507fa
#8e9c5640
#f99b66d6
#67fff375
#10f8c3e3

etc

Je ne prétendrai pas savoir comment tous les différents algorithmes de hachage sont utilisés, mais pour les utilisations non sécurisées (comme les liens #anchors), c'est pratique.

1
cbmtrx

toutes les méthodes ci-dessus sont bonnes, mais assurez-vous de savoir et de ne pas supposer que la chaîne générée est unique. Ce que j'ai fait dans le passé est devenu une fonction récursive qui vérifie la chaîne par rapport à ma base de données et si elle est unique, elle renvoie la valeur, sinon elle s'exécute à nouveau. Cela ne se produira guère mais dépend de la longueur de votre chaîne unique. C'est juste bon pour savoir son unique.

1
Darren