Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: skracanie linków
Forum PHP.pl > Forum > PHP
nowy_pehapowiec
Chciałbym napisać sobie stronę do skracania linków (podobną do Tinyurl.pl), ale nie jestem pewien algorytmu.
Weźmy taki adres:
http://adres.com/index.php?v=1111111111111...222222222222222
Tinyurl zamienia go na: http://www.tinyurl.pl?pPGv05sf, tak na prawdę na pPGv05sf bo http://www.tinyurl.pl? jest stałe w każdym zamienionym adresie.
Domyślam się, że w bazie mam tabele z dwoma kolumnami: pełny adres i skrócony adres. Pytanie jest jak skrócić adres, żeby skrót pozostał unikalny? md5 i sha1 są za długie. Ale połowa z md5 to właśnie 8 czyli tyle ile jest w Tinyurl. Czy wystarczy wygenerować dla adresu sumę md5 i wybrać z niej pierwszą połowę znaków? Co jeśli połowy sum dwóch różnych adresów będą takie same? Sprawdzać w tabeli i ewentualnie dodawać kolejne znaki z sumy? Czy warto się pokusić na jeszcze krótsze adresy np 6pierwszych znaków z md5? Może lepiej użyć fragmentu sha1 albo innego rozwiązania?
I jeszcze kwestia przekierowania. User podaje adres:
http://www.tinyurl.pl?pPGv05sf skrypcik pobiera z bazy pełny url. I trzeba go przekierować, czy header() wystarczy? Chciałbym uniknąć ostrzeżeń w przeglądarkach, że dochodzi do przekierowania. Zależy mi tez na wydajności.

Czy to będzie dobrze dobrze działać? Może coś trzeba poprawić?


pozdro
Spawnm
Najprostsze skracanie to tabela id , url
potem strona.pl?id=id_z_bazy
i pobierasz url where id=(int)$_GET['id']
na koniec nawet zwykłe header('location: '.$url);

id w bazie oczywiście auto_increment aby zachować unikalność.
tehaha
nie musisz haszować pełnego adresu url, możesz sobie wygenerować losowy kod 5 znakowy i przed dodaniem go do bazy sprawdzasz czy taki skrócony link już istnieje, jeśli tak to losujesz jeszcze raz
erix
Cytat
możesz sobie wygenerować losowy kod 5 znakowy

Losowy? Wraz ze wzrostem ilości rekordów będziesz miał problem z generowaniem unikalnego identyfikatora, bo może się parę razy powtórzyć. winksmiley.jpg

Co do praktycznego rozwiązania - BIGINT na ID, i aby nie były to długie liczby do przekazania w URL, tworzymy własny system liczbowy, który będzie zawierał - oprócz cyfr - także wielkie i małe litery oraz pewne znaki specjalne, które nie ulegają zamiany na %XX w adresie. Ale jakie to znaki, to odsyłam do odpowiedniego RFC dla URI.

Liczbę-ID zamieniamy na ten system liczbowy i voila - wystarczy go przekazywać w linkach.

O systemach liczbowych napisano już całkiem sporo; jeśli chodzi o przytoczone przeze mnie rozwiązanie, to YouTube chyba korzysta z takich identyfikatorów. winksmiley.jpg
nowy_pehapowiec
Losowe generowanie identyfikatorów odpada tego jestem pewien.

erix czy mógłbyś napisać coś więcej o tworzeniu takich literowych systemów liczbowych? Albo powiedzieć jak coś więcej o tym znaleźć?
RFC dla URI nie mówi mi nic:)

pozdro
erix
Cytat
erix czy mógłbyś napisać coś więcej o tworzeniu takich literowych systemów liczbowych?

A co więcej mogę napisać? Przecież to zwykła zamiana z systemu dziesiętnego na inne. Poszukaj w google, to nie gryzie.

Coś prawie jak szestnastkowy, tylko ma więcej znaków.
nowy_pehapowiec
To nie ma być system liczbowy a literowy i to już dla mnie jest kłopot. A google podaje co najwyżej systemy lotto w odpowiedzi smile.gif
Czy mógłbyś napisać coś więcej na ten temat? Jak zrobić sobie taki system liczbowoliterowy?

pozdro
Daniel Meger
Taka szybka implementacja systemu 0,1,2... 9,a,b,c,...,y,z,A,B,...,Y,Z.
Funkcje konwertują z systemu dziesiętnego na ten właśnie powyższy system sześćdziesięciodwójkowy.
Linie 2-20 to tylko generowanie tablic. Oczywiście dla wydajności skryptu, trzebaby było te wartości wpisać na stałe, ale mi się po prostu nie chciało tyle pisać.
  1. <?php
  2. $digitToAlfa = Array();
  3.  
  4. for ($i=0;$i<=9;$i++) {
  5. $digitToAlfa[$i] = $i;
  6. }
  7. $j = 'a';
  8. for ($i=10;$i<=35;$i++) {
  9. $digitToAlfa[$i] = $j;
  10. $j++;
  11. }
  12. $j = 'A';
  13. for ($i=36;$i<=61;$i++) {
  14. $digitToAlfa[$i] = $j;
  15. $j++;
  16. }
  17.  
  18. foreach ($digitToAlfa as $key => $value) {
  19. $alfaToDigit[$value] = $key;
  20. }
  21. /*
  22. echo '<pre>';
  23. print_r($digitToAlfa);
  24. print_r($alfaToDigit);
  25. echo '</pre>';
  26. */
  27.  
  28. function code($intNum) {
  29. global $digitToAlfa;
  30. $newNum = '';
  31. while ($intNum !== 0) {
  32. $newDigit = $intNum % 62;
  33. $intNum = (int)($intNum / 62);
  34. $newNum .= $digitToAlfa[$newDigit];
  35. }
  36. return strrev($newNum);
  37. }
  38.  
  39. function decode($strNum) {
  40. global $alfaToDigit;
  41. $newNum = 0;
  42. $strNum = strrev($strNum);
  43. for ($i=strlen($strNum)-1;$i>=0;$i--) {
  44. $newNum += $alfaToDigit[$strNum[$i]]* pow(62,$i);
  45. //echo "i: $i strNum: $strNum newNum: $newNum <br />";
  46. }
  47. return $newNum;
  48. }
  49.  
  50. $a = 4321;
  51. $b = code($a);
  52. echo $b;
  53. echo "<br /> \n";
  54. $c = decode($b);
  55. echo $c;
  56. echo "<br /> \n";
  57.  
  58. if ($a == $c) {
  59. echo "postacie pierwotna i wtorna sa identyczne.";
  60. } else {
  61. echo "postacie pierwotna i wtorna NIE sa identyczne.";
  62. }
  63.  
  64. ?>
erix
Tak trochę OT:
Cytat
To nie ma być system liczbowy a literowy i to już dla mnie jest kłopot.

To jest NADAL system liczbowy, tylko że oprócz cyfr 0-9 masz inne znaki. Nie ma czegoś takiego, jak system literowy. winksmiley.jpg Na dobrą sprawę, wg Twojego rozumowania system szesnastkowy powinien się nazywać liczbowo-literowy. winksmiley.jpg

Cytat
Oczywiście dla wydajności skryptu, trzebaby było te wartości wpisać na stałe, ale mi się po prostu nie chciało tyle pisać.

Wystarczyłoby 3x range + array_merge i array_combine.
Daniel Meger
Cytat(erix @ 30.04.2010, 22:46:28 ) *
Wystarczyłoby 3x range + array_merge i array_combine.

Czytelniej by być może było, ale czy wydajniej? Podejrzewam (chociaż tego dokładnie nie wiem), że te funkcje i tak opierają się na bardzo podobnych pętlach, stąd moja sugestia o wpisanie całych tablic wprost do kodu (albo poprzez include) - może zbyt eleganckie to nie jest, ale przy skrypcie, który będzie wykonywany bardzo wiele razy w ciągu sekundy, to może być kluczowa sprawa.
Crozin
Sposób wygenerowania tych tablic jest bez znaczenia. Dowolną metodą wygenerujesz je w pomijalnie małym czasie więc nie ma co sobie zaprzątać głowy mikrooptymalizacją.

Jedyną istotną rzeczą jest jakiś komentarz opisujący co fragment generujący je robi.
nowy_pehapowiec
dzięki za posty
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.