Алгоритм сокращения URL PHP
может ли кто-нибудь рекомендовать предпочтительный алгоритм для использования для сокращения URL? Я кодирую с помощью PHP. Первоначально я думал о написании чего-то, что начиналось бы с символа, такого как "a", и перебирало запросы, создавая записи в базе данных и, следовательно, увеличивая символ до b, c, d ... A, B и так далее в зависимости от обстоятельств.
однако меня осенило, что этот алгоритм может быть довольно тяжелым / неуклюжим, и может быть лучший способ сделать он.
Я немного почитал в Google, и некоторые люди, похоже, делают это с базовым преобразованием из столбца ID базы данных. Это не то, с чем я слишком хорошо знаком.
может кто-нибудь уточнить и объяснить мне, как это будет работать? Пару примеров кода тоже было бы здорово.
Я, очевидно, не хочу полного решения, как я хотел бы узнать, делая это сам, но просто объяснение/псевдо-код о том, как это будет работать отлично.
7 ответов
большинство служб сокращения просто используют счетчик, который увеличивается с каждой записью и преобразует базу с 10 до 64.
реализация в PHP может выглядеть так:
function encode($number) {
return strtr(rtrim(base64_encode(pack('i', $number)), '='), '+/', '-_');
}
function decode($base64) {
$number = unpack('i', base64_decode(str_pad(strtr($base64, '-_', '+/'), strlen($base64) % 4, '=')));
return $number[1];
}
$number = mt_rand(0, PHP_INT_MAX);
var_dump(decode(encode($number)) === $number);
на encode
функция принимает целое число, преобразует его в байты (pack
), кодирует его кодировкой Base-64 (base64_encode
), обрезает заднюю прокладку =
(rtrim
), и заменяет символы +
и /
by -
и _
соответственно (strtr
). The decode
функция является обратной функцией для encode
и делает прямо противоположное (за исключением добавление трейлинг обивка).
дополнительно использовать strtr
перевести исходная база-64 алфавит до URL и имя файла безопасный алфавит as +
и /
необходимо закодировать с помощью процентной кодировки.
вы можете использовать функцию base_convert для выполнения базового преобразования от 10 до 36 с идентификаторами базы данных.
<?php
$id = 315;
echo base_convert($id, 10, 36), "\n";
?>
или вы можете использовать некоторые из идей, представленных в комментариях на странице ниже:
я использовал, чтобы сломать ID по алгоритму, аналогичному тому, как преобразовать из десятичного в шестнадцатеричный, но он будет использовать 62 символа вместо 16 символов, которые будут использовать hex.
'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'
пример: если вы измените ID = 1234567890, вы получите kv7yl1 как ваш ключ.
предполагая, что ваш первичный ключ является INT и auto_increments, следующий код заставит вас идти=).
<?php
$inSQL = "INSERT INTO short_urls() VALUES();";
$inResult = mysql_query($inSQL);
$databaseID = base_convert(mysql_insert_id(), 10, 36);
// $databaseID is now your short URL
?>
EDIT: включен base_convert из ответа HGF. Я забыл base_convert в исходном посте.
Я принял" светлое " решение. По запросу пользователя я генерирую уникальный идентификатор (проверка конфликтов в БД) с этим фрагментом python:
url_hash = base64.b64encode(os.urandom(int(math.ceil(0.75*7))))[:6]
и хранить его в БД.
собственный PHP base_convert () хорошо работает для небольших диапазонов чисел, но если вам действительно нужно кодировать большие значения, рассмотрите возможность использования чего-то вроде реализации, представленной здесь, которая будет работать на базе 64 и выше, если вы просто предоставите больше законных символов для кодирования.
http://af-design.com/blog/2010/08/10/working-with-big-integers-in-php/
здесь попробуйте этот метод:
hash_hmac('joaat', "http://www.example.com/long/url/", "secretkey");
он предоставит вам хэш-значение, подходящее для профессионального сокращателя url, e.g:' 142ecd53'