[RESOLU] Générateur de code lettres + chiffres aléatoire en boucle

Carpediem
Invité n'ayant pas de compte PHPfrance

02 déc. 2014, 23:27

Bonjour,

Je suis de nouveau confronter à un problème pour mon jeu concours, je souhaiterais désormais générer des coupons chance que les personnes obtiendront en dehors du site et qui serviront à ajouter une chance supplémentaire pour le jeu concours.

Mon idée est la suivante.

- Générer 224 code aléatoires comme ceux ci :
$characts= 'ABCDEFGHIJKLMNPQRSTUVWXYZ';
$characts .= 'ABCDEFGHIJKLMNPQRSTUVWXYZ';	
$characts .= '123456789';

 
$code_aleatoire_1='';
$code_aleatoire_2='';
$code_aleatoire_3='';
$code_aleatoire_4='';
$code_aleatoire_5='';
$code_aleatoire_6='';
$code_aleatoire_7='';
$code_aleatoire_8='';
$code_aleatoire_9='';
$code_aleatoire_10='';
$code_aleatoire_11='';
$code_aleatoire_12='';
$code_aleatoire_13='';
$code_aleatoire_14='';
$code_aleatoire_15='';
$code_aleatoire_16='';
$code_aleatoire_17='';
$code_aleatoire_18='';
$code_aleatoire_19='';
$code_aleatoire_20='';

for($i=0;$i<12;$i++)    //12 est le nombre de caractères
	{ 
$code_aleatoire_1 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_2 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_3 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_4 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_5 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_6 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_7 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_8 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_9 .= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_10.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_11.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_12.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_13.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_14.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_15.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_16.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_17.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_18.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_19.= substr($characts,rand()%(strlen($characts)),1);
$code_aleatoire_20.= substr($characts,rand()%(strlen($characts)),1);
}

echo $code_aleatoire_1;?><br /><?php
    echo $code_aleatoire_2;?><br /><?php
    echo $code_aleatoire_3;?><br /><?php
    echo $code_aleatoire_4;?><br /><?php
    echo $code_aleatoire_5;?><br /><?php
    echo $code_aleatoire_6;?><br /><?php
    echo $code_aleatoire_7;?><br /><?php
    echo $code_aleatoire_8;?><br /><?php
    echo $code_aleatoire_9;?><br /><?php
    echo $code_aleatoire_10;?><br /><?php
    echo $code_aleatoire_11;?><br /><?php
    echo $code_aleatoire_12;?><br /><?php
    echo $code_aleatoire_13;?><br /><?php
    echo $code_aleatoire_14;?><br /><?php
    echo $code_aleatoire_15;?><br /><?php
    echo $code_aleatoire_16;?><br /><?php
    echo $code_aleatoire_17;?><br /><?php
    echo $code_aleatoire_18;?><br /><?php
    echo $code_aleatoire_19;?><br /><?php
    echo $code_aleatoire_20;?><br /><?php
Puis pouvoir envoyer la liste de 224 codes aléatoires directement en bdd dans une table avec un champ ID et un champ code aléatoire

Quelqu'un pourrait il m'expliquer le principe de ce genre de script. J'ai essayé avec du while, du for mais je ne trouve pas la méthologie pour parvenir à mes fins.

Merci d'avance =)

Eléphant du PHP | 453 Messages

03 déc. 2014, 11:36

Salut,

Peut être que cette piste devrait t'aider ;)
	$listeCaracteres = array_merge(range('a','z'),range('A','Z'),range(0,9));
	shuffle($listeCaracteres);
	$nbeCaractereMotDePasse = 8;
	
	$sortie = implode('',array_slice($listeCaracteres,mt_rand(0,count($listeCaracteres) - $nbeCaractereMotDePasse),$nbeCaractereMotDePasse));
	echo $sortie;
*code fait de tête

il n'y a plus qu'à boucler ;)
La Tux attitude avec les kiw'z syou plait
Komodo Edit - Inkscape - Dia

Mammouth du PHP | 2278 Messages

03 déc. 2014, 13:45

Développement de l'idée précédfente:
<?PHP
$tableau = array(); //sera le tableau des codes produits
$ListeCaracteres = array_merge(range('a','z'),range('A','Z'),range(0,9)); ca fait une seule liste de lettres min maj et chiffres
shuffle($ListeCaracteres); // on mélange la liste
$NombreCaracteres = count($ListeCaracteres);
$Longueur = 12; //longueur des codes attendus
$nieme = 1;//compteur de doublons

for($i=1; $i <=224; $i++)
{
       $code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
	//pour éviter les doublons qui sans ca sont innombrables, on remélange le tableau à l'apparition d'un doublon
	while (in_array($code, $tableau))
	{
		shuffle($ListeCaracteres);
		print "$nieme doublon";
		$nieme ++;
		$code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
	}
	$tableau[$i] = $code;
 }
foreach ($tableau as $valeur)
{
	// requete insertion dans BDD de $valeur
	print "<br>$valeur";
}
?>
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Eléphant du PHP | 453 Messages

03 déc. 2014, 14:57

Je n'avais pas vu le souci de l'unicité. Alors on peut faire largement plus simple :
for($i=1; $i <=224; $i++){
       echo md5(uniqid()).'<br>';
 }
Pour que la valeur soit plus simple à saisir, un petit substr() devrait aider.
La Tux attitude avec les kiw'z syou plait
Komodo Edit - Inkscape - Dia

ViPHP
ViPHP | 928 Messages

03 déc. 2014, 16:30

md5() ne garanti pas l'unicité. Certes il est improbable de tomber sur un doublon, mais si le code ne fait que 12 caractères, là il y a quand même certains risques.

J'aurais tendance à faire un do...while pour être sur :
$codes= [];
for ($i = 0; $i < 224; $i++)
{
   do
   {
      $code = substr(md5(uniqid()), 0, 12);
   }
   while (in_array($code, $codes));

   $codes[] = $code;
}

foreach ($codes as $code)
{
   // insertion en base
}

Carpediem
Invité n'ayant pas de compte PHPfrance

04 déc. 2014, 00:01

Bonsoir,

Je n'en demandais pas tant^^ j'ai adapté ce bout de code en y mettant ma requete sql mais le souci c'est qu'au bout de 30 secondes, php se mets en erreur (normal) et seulement 29 résultat sont dans la bdd. Comment accélérer le processus ?
<?php

$tableau = array(); //sera le tableau des codes produits
$ListeCaracteres = array_merge(range('a','n'),range('p','z'),range('A','N'),range('P','Z'),range(1,9));
shuffle($ListeCaracteres); // on mélange la liste
$NombreCaracteres = count($ListeCaracteres);
$Longueur = 12; //longueur des codes attendus
$nieme = 1;//compteur de doublons

for($i=1; $i<=224; $i++)
{
       $code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
        //pour éviter les doublons qui sans ca sont innombrables, on remélange le tableau à l'apparition d'un doublon
        while (in_array($code, $tableau))
        {
                shuffle($ListeCaracteres);
    
                $nieme ++;
                $code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
        }
        $tableau[$i] = $code;
 }
foreach ($tableau as $valeur)
{
        // requete insertion dans BDD de $valeur
        try
{
    $bdd = new PDO('mysql:host=localhost;dbname=coiffure', 'root', '');
    $bdd->query("SET NAMES UTF8");
    $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
}
catch(Exception $e)
{
        die('Erreur : '.$e->getMessage());
}

$req = $bdd->prepare ('INSERT INTO lucky_couponing(ID, code_aleatoire) 
                              VALUES(:ID, :code_aleatoire)');
$req->execute(array(
    'ID' => NULL,
    'code_aleatoire'=>$valeur));
}

?>
Cordialement

Eléphant du PHP | 453 Messages

04 déc. 2014, 00:17

Bonsoir,

Pas terrible et peut mieux faire (voir commentaires plus bas)
ini_set('max_execution_time', 0);
//ton script
ini_set('max_execution_time', 30); //J'ai mis 30. Mais en fait, tu dois saisir la conf d'origine. Pour se faire, php_info() et chercher (max_execution_time). Sinon dans le php.ini, tu trouveras la valeur aussi.
<<<EDIT
Dans le cas où tu n'as pas le choix. Tu dois utiliser PDO .- Alors il va falloir tout de même "logguer" tout ça et je pense que le système d'exception devrait t'aider également. Attention, PDO à sa propre classe Exception (2 catch ?).
EDIT;

Le mieux étant de générer tes N mots de passe et de créer une seule requête SQL. Mais par contre, PDO ne gère pas ce genre de requête. Regarde dans ce cas MySqli. Normalement, la requête ci-dessous devrait fonctionner :
INSERT INTO lucky_couponing (ID, code_aleatoire)
VALUES(1, 'unMotDePasse'),
VALUES(2, 'unAutreMotDePasse'),
VALUES(3, 'encoreUnMotDePasse'),
#etc.
#etc.
#jusqu'à
VALUES(224, 'encoreUnAutreMotDePasse');
@Genova : +1 puisqu'il y a le substr().
La Tux attitude avec les kiw'z syou plait
Komodo Edit - Inkscape - Dia

Carpediem
Invité n'ayant pas de compte PHPfrance

04 déc. 2014, 00:56

Bonsoir

Ne serait il pas possible d'entourer le bloc principal par un for avec à l'intérieur la génération de 14 codes qui s’insèrent en bdd et qui boucle 16 fois ?
for($i=0; $i<=16; $i++)
{

$tableau = array(); //sera le tableau des codes produits
$ListeCaracteres = array_merge(range('a','n'),range('p','z'),range('A','N'),range('P','Z'),range(1,9));
shuffle($ListeCaracteres); // on mélange la liste
$NombreCaracteres = count($ListeCaracteres);
$Longueur = 12; //longueur des codes attendus
$nieme = 1;//compteur de doublons

for($i=1; $i<=14; $i++)
{
       $code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
        //pour éviter les doublons qui sans ca sont innombrables, on remélange le tableau à l'apparition d'un doublon
        while (in_array($code, $tableau))
        {
                shuffle($ListeCaracteres);
                $nieme ++;
                $code = implode('',array_slice($ListeCaracteres,mt_rand(0,$NombreCaracteres - $Longueur),$Longueur));
        }
        $tableau[$i] = $code;
 }
foreach ($tableau as $valeur)
{
        // requete insertion dans BDD de $valeur
        try
{
    $bdd = new PDO('mysql:host=localhost;dbname=coiffure', 'root', '');
    $bdd->query("SET NAMES UTF8");
    $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
}
catch(Exception $e)
{
        die('Erreur : '.$e->getMessage());
}

$req = $bdd->prepare ('INSERT INTO lucky_couponing(ID, code_aleatoire) 
                              VALUES(:ID, :code_aleatoire)'); 
$req->execute(array(
    'ID' => NULL,
    'code_aleatoire'=>$valeur));
}



}
Peut on considérer qu'à chaque boucle c'est une nouvelle requête ? Dans ce cas, le compteur 0,30 secondes se réinitialise à chaque fois