Я пытаюсь начать работу с веб-разработкой, создав систему бронирования отелей для практики, и у меня возникла следующая проблема. Мне нужно создать два коротких, уникальных, без коллизий и только для целых хэшей, поскольку у меня есть следующее требование:
Номер должен быть достаточно длинным, чтобы быть правдоподобным для человека, так как он будет отправлен им по электронной почте в качестве кода бронирования, но также достаточно коротким, чтобы его мог использовать человек, так как 128-битный код бронирования является странным, и это также будет первичный ключ (уникальный идентификатор) для таблицы заказов и таблицы клиентов в базе данных.
Поэтому мне нужен один BookingId и один CustomersID. Я знаю, я мог бы использовать приращение в базе данных MySQL, но я хотел бы пойти более грубым путем здесь для целей обучения.
Почти все функции Hash создают более длинные хэши с цифрами и алфавитами. Но я хочу, чтобы хэши были короткими и целочисленными.
Вся хэш-логика будет выполняться в скрипте PHP прямо перед вставкой всех деталей в БД с использованием потрясающей функциональности PDO.
Теперь это ситуация:
У каждого Клиента есть один уникальный адрес электронной почты, который я знаю, когда он вставляет его в форму бронирования, поэтому я мог бы указать CustomerID на уникальном адресе электронной почты. Один клиент может иметь только один идентификатор клиента, но он может иметь несколько уникальных идентификаторов бронирования.
Таким образом, CustomerID может быть основан на адресе электронной почты, а BookingID может основываться на электронной почте и отметке времени.
Сложность здесь заключается в том, чтобы найти хеш-функцию, которая привела бы к 6-разрядному хешу без столкновений.
Как я могу сгенерировать эти два коротких, уникальных, без коллизий и хеш-целочисленных хэша, используя PHP?
Вместо того, чтобы хранить ваши «случайные идентификаторы» в вашей базе данных, я бы просто работал с классическим первичным ключом с автоматическим приращением. Для внешнего мира вы можете закодировать эти идентификаторы, чтобы они выглядели как длинные целые числа, которые вы желаете. И прежде чем запрашивать или сохранять что-либо в вашей базе данных, вы просто декодируете их обратно в фактический первичный ключ.
Что касается таблицы ваших клиентов, электронная почта звучит как допустимая опция для первичного ключа, но что, если пользователь решит изменить свой адрес электронной почты? Или что, если вы хотите поддерживать несколько адресов электронной почты в будущем? Я хотел бы также получить числовой идентификатор для клиентов, поскольку это простое и перспективное решение imo.
Нет необходимости заново изобретать колесо, я обычно использую эту маленькую библиотеку для этого:
https://github.com/ivanakimov/hashids.php
Кстати, не позволяйте имени обмануть вас, это, строго говоря, Encrypter, а не Hasher, поскольку он работает в двух направлениях.
Это позволяет вам установить собственный алфавит, поэтому ваше требование использовать только числовые значения не должно быть проблемой. Ваш код будет выглядеть примерно так:
$hasher = new Hashids(MY_APP_SALT, 6, '0123456789');
$hashId = $hasher->encode($idFromDb);
$id = $hasher->decode($idFromRequest);
Обновить:
Чтобы уточнить ваши вопросы в комментариях, вы также можете сделать
$customerId = $hasher->encode($email);
И действительно, пока параметры, которые вы предоставляете для построения $hasher
результаты останутся прежними.
Параметры для конструктора, в следующем порядке:
Кстати, я только что прочитал о альтернативная библиотека в документы если вы хотите работать только с числовыми значениями. Нет опыта с этим, но это может быть даже лучше подходит.
Других решений пока нет …