raccourcisseur d'url

Eléphanteau du PHP | 26 Messages

14 nov. 2013, 17:00

Bonjours,
j'ai envie de me créer une sorte de raccourcisseur d'url.

Ca marche, je génère une chaine aléatoire de chiffres et lettres qui est lier a l'url: mais comment faire pour déterminer quand il y aura plus de combinaison possible et rallonger la chaine aléatoire ?

En gros ça génère une chaîne aléatoire de 3 caractères, mais un jour il y a aura forcément une limite de combinaison possible surtout que ça détermine si elle est déjà utilisée et en demandé un autre, car aucune url ne peut avoir la même chaîne aléatoire.

Je pensais faire une fonction récursive. On peut calculer le nombre le nombre de possiblité suivant le nombre de caractère de la chaine ?


Sinon ce code est bon ?
	if(preg_match_all('#(^[http|https]+)#', $this->url, $return, PREG_SET_ORDER))
		{
// c'est un lien
		}
	else
		{
// c'est pas un lien
		}

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

14 nov. 2013, 19:20

salut,

sur le principe tu fait
- génération d'un code
- est ce que le code existe ?
- oui je recommence
- non je continu

Ajoute avant le calcul du nombre maximal de combinaison et le test du nombre de combinaison. Par exemple compter en base le nombre code qui exactement la longueur du code que tu génère. Si c'est égale au nombre maximal de possibilité tu ajoute un digit et ensuite tu génère le code (algo au dessus).
il faut que tu stock quelque part la longueur de la chaîne à générer.
je te conseil de gérer cela coté sgbd afin de pouvoir bloquer simplement le process pour éviter d'avoir deux process identique qui tourne en même tempos et arrive à faire la même chose.
C'est un cas plus ou moins improbable mais possible ;)


Si pourquoi ne pas simplement commencer sur un nombre de combinaison relativement élevée afin de ne pas être emmerdé ? ;)

si tu prend 10 digits avec en possibilité l'alphabet (minuscule et majuscule sans accent) plus les chiffres et pourquoi pas un peu de ponctuation tu auras au moins 62 possibilités par digits sur 10, 839299365868340224 possibilités si me souvient bien de mes cours de maths ;).

c'est beaucoup plus simple que de chercher si toutes les combinaisons ont étaient trouvée pour ajouter un digits. Et moins gourmand en ressource :mrgreen:

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 26 Messages

15 nov. 2013, 00:51

Au départ si je voulais commencer par un petit nombre c'est que ça fait beaucoup de possibilité de perdu si on commence a 4 ou 5 caractères dès le début surtout qu'il faut une url courte pour le reste du message sur twitter par exemple.

PS: comment tu arrives a trouver 839299365868340224 ?

Sinon mon regex est bon pour savoir si c'est un lien ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

15 nov. 2013, 10:00

PS: comment tu arrives a trouver 839299365868340224 ?
quelque chose comme nombre de combinaison sur un digit exposant nombre de digit (donc la en gros 62^10) tu trouveras une formule correct dans les cours de maths (lycée peut être).

pour ton masque non il n'est pas bon, simplement parce que tu demande http ou https en début de chaîne et que cela se répète. donc la chaîne ne peux que contenir http ou https plusieurs fois exemple httphttp.

Il existe des fonctions déjà prête pour ce genre de chose : filter_var avec le flag FILTER_VALIDATE_URL :mrgreen:


@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 26 Messages

15 nov. 2013, 13:27

C'est peut être bête, mais parfois on met des lien du genre google.fr alors j'ai voulu avec une petite condition rajouté un petit http:// devant et ça teste l'url. Par contre si j'ai juste un google, ça va faire: http://google et ça dit que l'url est valide.

Pour le calcule: j'ai fait:
26 pour les lettres(majuscules/minuscules) et 9 chiffre multiplier par le nombre de caractère que l'on veut: ((26*2)+9)*3.
Mais c'est forcément faux

Eléphant du PHP | 170 Messages

15 nov. 2013, 14:22

Bonjour,

- Il y a 10 chiffres et pas 9 (de 0 à 9 => 10 chiffres)
- Ce n'est pas "multiplier par 3" mais "puissance 3"

donc ((26*2)+10)^3=238328

(sinon il me semble que les url sont insensibles à la casse => je ne différencierais pas les majuscules/minuscules)

Eléphanteau du PHP | 26 Messages

15 nov. 2013, 17:44

Les A1A, A1a, Aa1, a1a, a1A est différent^^.

Merci, j'ai trouvé, mon erreur^^, par contre quand je fais ton calcul je trouve 61: echo $calcule = ((26*2)+10)^3;
Mais si je fais ça je trouve le même nombre:
$calcule = ((26*2)+10);
echo $calcule*$calcule*$calcule;

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

15 nov. 2013, 18:15

pour le nombre de combinaison une petite question à google et on a des exemples http://forums.futura-sciences.com/mathe ... ffres.html

donc 62 possibilités sur un digits sur X digits tu auras 62^X (62 "puissance" X) combinaison.
Dans l'exemple c'est 10 chiffres sur 4 digits.
en php tu peux utiliser la fonction bcpow

bon test :)

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 26 Messages

15 nov. 2013, 21:39

Par contre c'est bien beau de comparer si le nombre de possibilité est atteint et d'augmenter d'un caractère... mais comment voir si la combinaison n'est pas déjà utilisé ?
Je me vois mal comparer presque toute la BDD pour voir si je peux utiliser la combinaison, car si j'ai 100 liens ça sera pas pareil par rapport a 100 000...

----

Question bête: mysql peut pas faire en sorte d'avoir une clé unique qui soit avec des lettres(majuscules/minuscules) et des chiffres d'une certaine taille et l'augmenter quand toute les possibilité sont utilisé ?

Eléphant du PHP | 170 Messages

16 nov. 2013, 07:14

Si on incrémente une variable et qu'on la passe en base 62 (en utilisant les chiffres, les minuscules et les majuscules pour le codage)

par exemple :

7403905 en base 62 => v45P
+1
7403906 en base 62 => v45Q
+1
7403907 en base 62 => v45R
+1
etc ...

- on est sûr que la valeur n'a jamais été prise.
- l'augmentation du nombre de caractères se fait automatiquement si besoin.

Ça conviendrait ? ou tu veux absolument que ce soit aléatoire ?

Eléphanteau du PHP | 26 Messages

16 nov. 2013, 12:13

Le but d'y faire aléatoirement c'était pour que ça soit unique avec chiffres et lettres pour avoir toute les combinaison possible, mais ton idée est génial!!! Je trouve juste dommage qu'au début ça commence a un caractère, mais c'est pas grave^^.
En plus même pas de contrôle a faire en BDD si j'utilise l'id qui est forcément unique!!! On peut même tester la class sur l'id de la table et donc ça évite d'avoir une colonne avec la clé, c'est encore mieux.

J'ai trouvé cette fonction:
<?php
/**
 * Base n encode /decode
 * @author CrazyCat
 * @package Mephisto::Maths
 */
class NBase {
 
    /**
     * Array of chars to use
     * @var array
     */
    private $vals = array(
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    );
 
    /*
     * Base to use
     * @var int
     */
    private $base = 10;
 
    /**
     * Constructor
     * @param int $n Base to use
     */
    public function __construct($n=10) {
        $this->setBase($n);
    }
 
    /**
     * Sets the destination base
     * @param int $n Base to use
     */
    public function setBase($n=10) {
        if ($n < 2 || $n > count($this->vals)) {
            $n = count($this->vals);
        }
        $this->base = $n;
    }
 
    /**
     * Gets the destination base
     * @return int
     */
    public function getBase() {
        return $this->base;
    }
 
    /**
     * Encodes integer to new base
     * @param integer $b10 Integer in base 10
     * @return string
     */
    public function encode($b10) {
        $bn = '';
        $current = $b10;
        while($current > 0) {
            $rest = $this->modulo($current, $this->base);
            $bn .= $this->vals[$rest];
            $current = floor($current/$this->base);
        }
        return strrev($bn);
    }
 
    /**
     * Decodes string from base
     * @param string $bn String in base n
     * @return integer
     */
    function decode($bn) {
        $bn = strrev($bn);
        $b10 = 0;
        for($i=0; $i<strlen($bn); $i++) {
            $item = substr($bn, $i, 1);
            $pos = array_search($item, $this->vals);
            $b10 += $pos * pow($this->base, $i);
        }
        return $b10;
    }
 
    /**
     * Calculates a modulus
     * To use because native "%" is buggy
     * for big values
     * @param integer $val
     * @param integer $div Divisor
     * @return integer remainder
     */
    function modulo($val, $div) {
        $r = $val - (floor($val/$div)*$div);
        return $r;
    }
}

// Un petit test:
	for($i=1; $i<=100; $i++)
	{
$test = $i;
$bn = new NBase(62);
$try1 = $bn->encode($test);
$try2 = $bn->decode($try1);
echo $test, ' gives in base ', $bn->getBase(), ': <b>', $try1, '</b> decoded as ', $try2, '<br>';
	}
?>

Eléphant du PHP | 170 Messages

16 nov. 2013, 20:42

Je trouve juste dommage qu'au début ça commence a un caractère
Tu peux fixer une taille minimum et utiliser str_pad() pour compléter avec des "0" à gauche pour atteindre cette taille.
Par exemple pour une taille mini de 3 caractères : str_pad('ab', 3, 0, STR_PAD_LEFT)


J'avais bricolé une fonction pour passer en base 62 :
<?php

function base62($v_base10) {
	$v_base62 = '';
	while($v_base10 > 0)
	{
		$v_base62 = substr('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $v_base10%62, 1) . $v_base62;
		$v_base10 = floor($v_base10 / 62);
	}
	return $v_base62;
}

$v = 7403905;

echo $v, ' => ', base62($v);

?>

Eléphanteau du PHP | 26 Messages

18 nov. 2013, 12:27

J'ai pas tester ta fonction, mais elle a l'air bien plus simple que celle que j'ai donnée.

Sinon mon regex est juste ? Je veux vérifier qu'il y est au moins une lettre majuscule et minuscule et un chiffre:
	
	if ( preg_match("#[A-Z]#", $_POST['mot_de_passe']) AND preg_match("#[0-9]#", $_POST['mot_de_passe'])  AND preg_match("#[a-z]#", $_POST['mot_de_passe']) ) 
		{
// Tous les caractères demandé
		}
	else
		{
echo 'erreur';
		}

Autre chose:

J'ai un fichier activation_compte.php et j'aimerais des lien du style:
http://site.fr/activation_compte/13Bu70 ... 1040pE33oM
Sa m'affiche bien ma page, sauf que ma clé ne fonctionne pas(Notice: Undefined index: cle in ):

Code : Tout sélectionner

RewriteRule ^activation_compte/([0-9-a-z-A-Z]+)$ activation_compte.php?cle=$1 [L]
Par contre avec un - ça fonctionne, comment régler le problème ?

Code : Tout sélectionner

RewriteRule ^activation_compte-([0-9-a-z-A-Z]+)$ activation_compte.php?cle=$1 [L]

ViPHP
ViPHP | 2577 Messages

18 nov. 2013, 15:50

Bonjour,

Je verrais bien un array qui fait correspondre un nombre entre 0 et 61 à un caractère et réciproquement.
Ensuite, tu découpes l'auto-incrément en base 62 et tu transformes en caractères suivant le tableau et réciproquement.
Tu n'a besoin que d'une table de 2 colonnes : id (auto-incrément) et url.

Eléphanteau du PHP | 26 Messages

18 nov. 2013, 18:03

Moi j'ai vu plus complexe: un statut: si l'url a été supprimé ou signalé et donc va devoir être vérifié, la date de création de l'url...

Sinon tu peux me répondre pour mon .htaccess ? C'est assez embêtant comme problème.