Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Unikatowy, losowy ID
Forum PHP.pl > Forum > PHP
graft
Witam wszystkich.

Napisałem prosty skrypt rejestracji użytkowników. Dodatkowo chcę, aby każdy z użytkowników otrzymywał unikatowy identyfikator o formacie (np. U1234567), czyli jak widać stała litera "U" oraz 7-cyfrowa unikatowa, losowa liczba.

Napisałem coś takiego:
  1. <?php
  2.  
  3.  $sql = "SELECT user_new_id FROM tbl_users";
  4.  $result = mysql_query($sql)
  5.  or die ("Błąd: " . mysql_error()); 
  6.  
  7.  do {
  8.  $istnieje = 0;
  9.  $wynik = '';
  10.  
  11.  for($i=0;$i<7;$i++) { //7-cyfrowa
  12.  $losuj = rand(0,9); 
  13.  $wynik .= $losuj;
  14.  }
  15.  $unikat = 'U'.$wynik;
  16.  
  17.  while($row = mysql_fetch_array($result)) {
  18. if($unikat==$row['user_new_id']) {
  19.  $istnieje = 1;
  20.  }
  21.  } //end while 
  22.  
  23. }
  24.  while ($istnieje == 1); //end do while
  25.  echo $unikat;
  26.  
  27. ?>


Niestety nie działa jak powinno. Tzn. jeśli jako pierwsza liczbę wylosuje ciąg którego nie ma w bazie to jest OK. Natomiast kolejna wylosowana liczba lubi się powtórzyć (dla ułatwienia ustawiłem 1-cyfrową liczbę i wpisałem do bazy U1-U7, czyli możliwe powinno być jedynie uzyskanie ciągów: U8,U9 oraz U0)

Jeśli ktoś widzi błąd lub zna lepszy sposób na rozwiązanie problemu unikatowego, losowego ID byłbym wdzięczny za wskazówki.
misiek172
ale po co ci taki? nie wystarczy kolumna ID i auto_increment? przecierz czy bedzie user mial kod U12324 czy 12 to jedno i to samo smile.gif

ale jeśli tak nalegassz to ustawiasz sobie w danej kolumnie powiedzmy ID właściwość UNIQUE (czy jakoś tak to sie pisze tongue.gif)

i poprostu skrypt który generuje taki numerek z U i próbuje wklepac do bazy i intrukacja warunkowa IF numer sie nie wklepał to zgeneruj jeszcze raz i tak az sie zgeneruje nie powtarzalny smile.gif
graft
Cytat(misiek172 @ 24.03.2007, 18:05:19 ) *
ale po co ci taki? nie wystarczy kolumna ID i auto_increment? przecierz czy bedzie user mial kod U12324 czy 12 to jedno i to samo smile.gif

Taki mam wymóg

Cytat(misiek172 @ 24.03.2007, 18:05:19 ) *
i poprostu skrypt który generuje taki numerek z U i próbuje wklepac do bazy i intrukacja warunkowa IF numer sie nie wklepał to zgeneruj jeszcze raz i tak az sie zgeneruje nie powtarzalny smile.gif


Może zadam pytanie tak: W jaki sposób właściwie porównać, czy wylosowana liczba nie występuje w bazie, a jeśli występuje, niech losuje nowąquestionmark.gif?
devnul
może poprostu rób identyfikatory kolejne a do wygenerowanego dodawaj milion i masz zawsze 7 cyfrowy uid
Babcia@Stefa
  1. <?php
  2. $powtarza_sie = '2323';
  3. while (true)
  4. {
  5. $losuj = rand(1, 100);
  6. if($losuj !== $powtarza_sie)
  7. break;
  8. }
  9. ?>


Tylko odpowiednio sobie go przerób.

@edit
OMG !
To robisz np.
  1. <?php
  2. $rand = rand(1, 3);
  3. if($rand == 1)
  4. $losuj = rand(10, 1000);
  5. elseif($rand == 2)
  6. $losuj = rand(100, 10000);
  7. else
  8. $losuj = rand(1000, 100000);
  9. echo 'Twój id: ' .$losuj;
  10. ?>


lub

  1. <?php
  2. $rand = rand(1000, 100000);
  3. $losuj = rand($rand, 10000000);
  4. ?>


Dziękuję, Babcia@Stefa
devnul
taa jasne Babciu, a jak w bazie będzie miał milion rekordów to napewno szybko wylosuje taki ktry będzie unikalny - good 4 you
UDAT
Zrób sobie skrypt generujący losową permutację liczb 7 cyfrowych i zapisującą ją do pliku.
Potem przy tworzeniu kolejnych userów dawaj kolejne linie z pliku jako UID.

Plik ze wszyskimi permutacjami 7 cyfrowych liczb zajmie około 10^7B = 10MB.
Możesz oczywiście przyciąć plik do np. 10^6 UID
Kicok
Cytat
Zrób sobie skrypt generujący losową permutację liczb 7 cyfrowych i zapisującą ją do pliku.
Potem przy tworzeniu kolejnych userów dawaj kolejne linie z pliku jako UID.

Plik ze wszyskimi permutacjami 7 cyfrowych liczb zajmie około 10^7B = 10MB.
Możesz oczywiście przyciąć plik do np. 10^6 UID

Ale po co? blink.gif


  1. <?php
  2.  
  3. // Inicjujemy generator liczb losowych dla PHP < 4.2.0
  4. srand( array_sum(explode(',', microtime())) );
  5. $istnieje = false;
  6. do 
  7. {
  8. // Losujemy liczbę
  9. $losuj = rand(0, 9999999);
  10.  
  11. // Jeśli jest zbyt krótka, to uzupełniamy ją zerami
  12. $losuj = str_repeat('0', 7-strlen($losuj)) . $losuj;
  13.  
  14. // Dodajemy 'U' na początku
  15. $losuj = 'U' . $losuj;
  16.  
  17.  
  18. // Sprawdzamy, czy ktoś ma już takie ID
  19. $result = mysql_query('SELECT 1 FROM tbl_users WHERE (user_new_id = '' . $losuj . '');');
  20. $istnieje = (mysql_num_rows($result) > 0);
  21. }
  22. while($istnieje);
  23.  
  24. // Znaleziono unikatowe ID:
  25. echo($losuj);
  26.  
  27. ?>


W przypadku 7 cyfr ciężko jest wylosować już wygenerowane ID, więc w znacznej większości przypadków wykonywane będzie jedno zapytanie SQL. No chyba, że przybędzie sporo wierszy w tej tabeli. Wtedy można się będzie zastanowić nad pobraniem wszystkich identyfikatorów do tablicy i sprawdzaniu unikalności przy pomocy in_array" title="Zobacz w manualu PHP" target="_manual

PS. Pisane z palca, mogą być błędy
devnul
ale co będize przy powiedzmy paru milionach wpisów? w najlepszym wypadku będzie to bardzo wolno działało
graft
Dzięki Kicok. Twoje rozwiązanie jest dla mnie jak najbardziej OK. 7-cyfrowy identyfikator powinien spokojnie wystarczyć i przypadków wygenerowania istniejącego numeru będzie raczej niewiele.

Mam tylko pytanie: Czy koniecznie muszę inicjować generator liczb losowych?
  1. <?php
  2. ?>

Czy mogę go w przypadku PHP5 pominąć?

Dlaczego gdy zainicjowany jest generator, przy odświeżaniu strony wylosowana liczba jest zawsze taka sama. Natomiast, gdy wyłącze generator losuje za każdym razem inną liczbę.
PS. Wiem, że to pytanie klasyfikuje się raczej do działu "przedszkole" - tak tylko pytam z ciekawości.


Pozdrawiam
JaRoPHP
Cytat(graft @ 25.03.2007, 20:32:51 ) *
Mam tylko pytanie: Czy koniecznie muszę inicjować generator liczb losowych?

http://pl.php.net/manual/pl/function.rand.php
Cytat
Od PHP w wersji 4.2.0 nie ma potrzeby inicjalizować generatora liczb losowych funkcją srand() lub mt_srand(), ponieważ dzieje się to automatycznie.
misiek172
ehh
no to sobie zrób to ID i autoincrement ale żeby nie zaczynało się od 1

tylko od np.: 50000 i bedzie liczyl

50001
50002

itd

i po wyciagnieciu dajesz przed id literke U smile.gif
graft
Cytat(JaRoPHP @ 25.03.2007, 23:16:33 ) *


Ojj proszę Cię! Nie odsyłaj mnie do manuala. Oczywiście, zajrzałem najpierw do niego, nie znalazłem odpowiedzi na pytanie: dlaczego gdy zainicjuje generator losuje ciągle taką samą liczbę gdy odświeżam stronę, a jeśli odznaczę inicjowanie wyświetla różne liczby przy odświeżaniu strony.

OK, może gdzieś tam na dole w przykładach w manualu jest odpowiedź. Ale mimo wszystko postanowiłem zadać to pytanie, skoro już jest ten post.

A teraz Ty mi dajesz linka, jakbym co najmniej pytał się o wyjaśnienie co robi "echo" :roll2:
misiek172
takie komentarze możesz przemilczeć a nie robić komuś wyrzuty, nikt niewie kto ma jaki stan wiedzy PHP wiec chłopak odesłał cie do manuala, skad ma wiediec czy ty to czytales czy wogole wiesz jak wylaga skoro nie potrafisz sobie poradzic z głupim problemem unikatowości ID :| forum jest od tego aby pomagac a nie komentować posty
devnul
nie no bez przesady - forum to przede wszystkim dyskusja a nie tylko pomoc - od pomocy to jest właśnie manual a od rozwiązywania wątpliwości, dyskusji itp forum
JaRoPHP
Cytat(graft @ 25.03.2007, 21:33:13 ) *
Ojj proszę Cię! Nie odsyłaj mnie do manuala.
Nie odesłałem Cię do manuala @graft, tylko zacytowałem jego fragment, który jest odpowiedzią na Twoją wątpliwość (która mnie zastanawia, czy zadanie "Oczywiście, zajrzałem najpierw do niego" jest prawdziwe...):
Cytat(graft @ 25.03.2007, 20:32:51 ) *
Mam tylko pytanie: Czy koniecznie muszę inicjować generator liczb losowych?
Czy mogę go w przypadku PHP5 pominąć?
sf
Nie róbcie tego w PHP. Tylko zrobić procedurę składowaną, która się tym zajmie. Ułatwi to np. późniejsze integracje z jakimś forum.
Kicok
Cytat
nie znalazłem odpowiedzi na pytanie: dlaczego gdy zainicjuje generator losuje ciągle taką samą liczbę gdy odświeżam stronę, a jeśli odznaczę inicjowanie wyświetla różne liczby przy odświeżaniu strony.


srand() przyjmuje jako parametr liczbę całkowitą, która służy później do obliczania liczb pseudolosowych w funkcji rand(). A jako że w moim kodzie był błąd, to do funkcji przekazywana była zawsze liczba 0. Zamień sobie linijkę:
  1. <?php
  2. ?>

na:
  1. <?php
  2. srand( array_sum(explode(' ', microtime()))*10000 );
  3. ?>

lub na:
  1. <?php
  2. ?>

i problem zniknie.
Turgon
Dla mnie śmieszny trochę problem. Ja bym to robił używając takich id jak sesji smile.gif:
  1. <?php
  2. $sid = md5(strtoupper(sha1(crypt(mt_rand()))));
  3. ?>


istnieje strasznie małe prawdopodobieństwo wystąpienia identycznego id...
Sedziwoj
Cytat(graft @ 24.03.2007, 16:57:26 ) *
Witam wszystkich.

Napisałem prosty skrypt rejestracji użytkowników. Dodatkowo chcę, aby każdy z użytkowników otrzymywał unikatowy identyfikator o formacie (np. U1234567), czyli jak widać stała litera "U" oraz 7-cyfrowa unikatowa, losowa liczba.

Mam głupie pytanie, ale co za różnica czy zrobisz U0000001 i iterację czy wylosujesz? Przecież w końcu i tak się te liczby trafią...
Jak chcesz na starcie dużą liczbę, to wymyśl jakąś a potem odejmuj od niej, jak po odjęciu będzie <0 to to dodajesz do niej...
Bo generowanie losowego i spr. czy nie występuje jest głupie. Ale jak już koniecznie potrzebujesz i nic nie możesz z tym zrobić, to najrozsądniej użyć random i spr. czy już podane id nie istnieje.

PS Turgon to miały być cyfry dziesiętne nie szesnastkowe
graft
Cytat(Sedziwoj @ 27.03.2007, 01:51:41 ) *
Mam głupie pytanie, ale co za różnica czy zrobisz U0000001 i iterację czy wylosujesz? Przecież w końcu i tak się te liczby trafią...

No cóż, bywało w przeszłości (nie konta internetowe), że przy 100 kliantach, toczone były istne wojny: "dlaczego Kowalski ma nr 7, Nowak nr 1, a Malinowski 'tylko 92 ?".
Dodatkowo, będzie wyszukiwarka po ID użytkownika, oraz wizytówka o odpowiedniej nazwie (też z ID) - chcę uniknąć sytuacji, żeby użytkownicy dodawali sobie do swojego ID 1 i oglądali, kto bezpośrednio po nich utworzył konto.

Teraz, kiedy każdy z kontrahentów będzie miał losowy numer i na dodatek 7, czy 8-cyfrowy problem powinien zniknąć. Na dodatek nie przewiduję aby wpisów do bazy było X milionów, więc wygenerowanie ID, który jest w bazie powinno być raczej rzadkością.

Tak mi się wydaje

PS. Kicok - raz jeszcze dzięki za odpowiedzi.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.