Dans mon système, chaque client a son propre dossier, dont le nom est généré par la fonction rand ().
Je veux m'assurer que la valeur de $ variable aléatoire reste toujours unique. J'ai créé le code ci-dessous qui devrait:
Mais je ne suis pas sûr que cela fonctionne comme il se doit et est un moyen efficace de faire les étapes ci-dessus.
$random = rand(pow(10, 3-1), pow(10, 3)-1);
$path_validator = 'build/'.$random;
if(is_dir($path_validator)) {
$random = rand(pow(10, 3-1), pow(10, 3)-1);
}
else
{
mkdir('build/crm/'.$random, 0777);
}
$random doit être un nombre aléatoire à 3 chiffres
3 Réponses :
Utilisez simplement un GUID. http://php.net/manual/en/function.com-create-guid.php
Ce sera très probablement unique.
Merci pour votre aimable réponse, j'ai oublié de mentionner que $ random doit être un nombre aléatoire à 3 chiffres, a mis à jour ma question!
Comme one-liner :)
while(!is_dir($id = uniqid()) && !mkdir($id));
Numéro à 3 chiffres:
while(!is_dir($id = rand(100,999)) && !mkdir($id));
EDIT (à l'épreuve des balles - espérons-le):
while(count(glob('*', GLOB_ONLYDIR))<899 && !@mkdir('sub.' . rand(100,999) . '.domain.com'));
Explication:
Interrompra immédiatement si 899 répertoires sont présents.
@mkdir pour essayer de créer un répertoire. S'il échoue, mkdir retournera false pour que la boucle continue.
Plus de is_dir pour empêcher la condition de course d'exécution simultanée.
Exemple:
Bob vérifie is_dir('333')
Joe vérifie is_dir('333')
Bob tente de créer le répertoire '333' - succès.
Jeo tente de créer le répertoire «333» - échec.
uniqid renvoie des nombres et laisse comme il utilise des valeurs hexadécimales. OP veut des nombres seulement et seulement 3 chiffres.
et que se passe-t-il s'il y a déjà 300 fichiers dans un répertoire et que l'aléatoire reste dans la plage de 1 à 300 par exemple ..
il continuera à marcher jusqu'à ce qu'il obtienne une place libre - eh bien s'il n'y a pas de place libre, il essaiera pour toujours ... et à jamais. C'est pourquoi uniqid est le meilleur choix
@Pilan, le dossier est le sous-domaine crm _ ***. L'idée d'exemple.org est de rester simple et pas plus de 1000. C'est pourquoi j'ai besoin d'un nombre aléatoire à 3 chiffres. mais la boucle infinie n'est pas une option. je pense que je dois changer quelque chose dans mon programme.
"il continuera à marcher jusqu'à ce qu'il obtienne une place libre" oui je sais @Pilan qu'il continuera à faire ça..Bruteforcing jusqu'à ce que vous en obteniez un gratuit ce n'est pas un algorithme intelligent en fait cela peut prendre de plus en plus de temps plus les fichiers sont ajouté .. Le code peut être bloqué pendant une heure lorsque tous les numéros sauf les 5 à 10 derniers sont donnés en supposant que la limite de temps n'est pas définie.
Eh bien, quelle est l'option? Vous devez vérifier. Si vous avez une solution pour cela, je serais heureux de l'entendre :) - J'en ai une, mais ce n'est plus aléatoire, si vous pouviez appliquer un algorithme pour trouver une place libre, ce ne serait pas aléatoire - voyez le problème? :RÉ
Pourquoi ajoutez-vous un suppresseur d'erreur ( @ ) à la fonction mkdir ?
Parce que je ne veux pas d'erreurs de mkdir si je frappe un répertoire existant - j'ai sauté le is_dir donc la vérification est implicite maintenant - je ne connais plus de poème: D
Mais n'est-ce pas le cœur de la question OP pour vérifier s'il existe un répertoire existant et relancer les dés si c'est le cas?
C'est ce que fait le code. mkdir renvoie false si le répertoire existe - donc la boucle continue - si je place le is_dir là-dedans, il y a une infime chance de condition de is_dir . Voulait le rendre à l'épreuve des balles: P
1) Parce que vous vérifiez déjà si la valeur existe, son unicité n'a pas vraiment d'importance en termes de comparateurs.
2) Parce que vous ne voulez qu'un nombre à "3 chiffres", il n'y a que 1000 possibilités, ce qui rend la demande d'une valeur unique assez dénuée de sens, à l'échelle de calcul des choses.
Par conséquent, vous pouvez simplement utiliser mt_rand car:
De nombreux générateurs de nombres aléatoires d'anciennes bibliothèques ont des caractéristiques douteuses ou inconnues et sont lents. La fonction mt_rand () est un remplacement de l'ancien rand (). Il utilise un générateur de nombres aléatoires avec des caractéristiques connues utilisant le  »Mersenne Twister, qui produira des nombres aléatoires quatre fois plus rapidement que ce que fournit la libc rand () moyenne.
Et comme vous recherchez une plage de nombres définie, vous pouvez simplement définir cette plage dans l' mt_rand fonction mt_rand .
Donc:
// Below lines are only to show the parts to generate $random var.
// $random = mt_rand(0,999); //generate random number between 0 and 999
// $random = sprintf('%03d', $random); //forces value to 3-digits. ie: 005
//
// Real code begins here:
do {
$random = sprintf('%03d',mt_rand(000,999));
$path_validator = 'build/'.$random;
clearstatcache(); // the directory checker result is cached.
}
while(is_dir($path_validator) || !mkdir('build/crm/'.$random, 0777));
(Voir aussi sprinf )
0777 .mt_rand soit plus aléatoire que rand il existe toujours une probabilité relativement élevée que deux utilisateurs génèrent tous les deux les mêmes valeurs à 3 chiffres. Être averti!!
$random = mt_rand(000,999); également sujet à des conditions $random = mt_rand(000,999); très improbables lorsque $random = mt_rand(000,999); ; génère le même nombre lorsque deux clients ou plus l'exécutent en même temps, c'est une petite chance que je sais mais vous connaissez la loi de Murphy, non? Tout ce qui peut mal tourner va mal
C'est aussi probable que je me fasse immédiatement caresser par une lumière ... connexion perdue
@RaymondNijland Je suis entièrement d'accord, mais ce sont les critères définis par l'OP. avec seulement 1000 itérations, le risque de conflit est relativement élevé.
"avec seulement 1000 itérations, il y a une chance comparativement élevée d'un conflit" vrai je n'ai même pas regardé la gamme dont le topicstarter avait besoin / voulait.
"Mais je ne suis pas sûr que cela fonctionne comme il se doit et est un moyen efficace de faire les étapes ci-dessus." Oui, il semble également enclin à des conditions de course très improbables lorsque
$random = rand(pow(10, 3-1), pow(10, 3)-1);génère le même nombre lorsque deux clients ou plus l'exécutent en même temps, c'est une petite chance mais vous connaissez la loi de Murphy, non? Tout ce qui peut mal tourner va malJe suppose que le client a son propre identifiant (dans la base de données), non? Pouvez-vous utiliser l'ID comme nom de dossier? Sinon, utilisez un Guid comme Tim proposé.
@Raymond Nijland, hmm vous voulez dire que si deux personnes ou plus ouvrent l'url exactement au même moment, rand () calculera le même nombre pour les deux? Et puisque le dossier n'est pas encore créé, mon validateur ne fonctionnera pas? ps peuvent-ils tous chemin mkdir () sans erreur également?
@Devator, malheureusement il n'y a pas de structure complexe derrière cette simple question. Le dossier est un sous-domaine et qui est généré avant l'enregistrement de l'utilisateur.
Que se passera-t-il lorsque vous atteindrez votre 1 000e client?
@Tim, c'est un environnement de démonstration où le nombre maximum de testeurs / dossiers doit être inférieur à 1000.
"hmm vous voulez dire que si deux personnes ou plus ouvrent l'URL exactement au même moment, rand () calculera le même nombre pour les deux?" Oui c'est ce que je voulais dire .. Au fait, ce code est-il connecté à une base de données? Je laisserais la base de données générer un nombre par customer_id, rapide et sans danger pour les conditions de course.
@Tim eh bien je vais tout foutre en l'air et partir en vacances pendant un mois chez les babados. Enfer ouais! Le client 1001 peut attendre.
Utilisez une base de données comme je l'ai dit avant de la rendre extensible, vous n'avez pas à réécrire tout le code pour prendre en charge le 1001e client comme le dit @Tim. Le moteur de table MyISAM peut générer un nombre dans et entre les groupes dans ce cas ID client voir démo .. Attendez, je viens de vous conseiller d'utiliser bien MyISAM c'est le seul cas valide où je choisirais MyISAM sur InnoDB car InnoDB ne prend pas en charge cette fonctionnalité.
@RaymondNijland après avoir examiné ma déclaration, je trouve que les versions modernes d'InnoDb ont maintenant la plupart des fonctionnalités de MyISAM.
"après avoir examiné ma déclaration, je trouve que les versions modernes d'InnoDb ont maintenant la plupart des fonctionnalités de MyISAM." Oui, InnoDB n'a pas pris en charge les index FULLTEXT depuis le début, à peu près sûr que c'était l'un de vos points. InnoDB est aussi beaucoup plus rapide puis MyISAM au sens général lorsqu'il est configuré correctement car les données et index InnoDB peuvent être chargés dans la mémoire où pour MyISAM seul l'idnex est sur la mémoire.
@Raymond Nijland, comme mentionné précédemment, il y a beaucoup plus derrière cette fonction simple qui est un peu compliquée à expliquer dans ce format, il y a des raisons pour lesquelles je ne veux pas utiliser de base de données, dans le cas de DB, je pourrais simplement créer 1000 enregistrements à l'avance et attribuez-le en fonction des statues de ligne actives / inactives. mais votre commentaire sur MyISAM est très apprécié, il résoudra probablement mon autre problème pour un projet différent.