Я пытаюсь создать случайный серийный номер, чтобы надеть голографические наклейки, чтобы клиенты могли проверить подлинность приобретенного продукта или нет.
Предисловие: как только вы вводите это и запрашиваете этот код, он будет нулевым, поэтому в следующий раз, когда вы это сделаете снова, вы получите сообщение о том, что продукт может быть поддельным, потому что код уже используется.
Учитывая, что я должен сделать эту систему для фабрики, которая производит не более 2/3 миллионов штук в год, для меня немного сложно понять, как настроить все, по крайней мере в первый раз...
Я думал о 20-значном коде в 4-х группах (без букв, потому что пользователю очень легко читать и вводить код)
12345-67890-98765-43210
Это то, что я считаю самым простым способом сделать все:
function mycheckdigit()
{
...
return $myserial;
}
$mycustomcode="123";
$qty=20000;
$myfile = fopen("./thefile.txt","w") or die("Houston we got a problem here");
//using a txt file for a test, should be a DB instead...
for($i=0;$i<=$qty;$i++) {
$txt = date("y").$mycustomcode.str_pad(gettimeofday()['usec'],6,STR_PAD_LEFT).random_int(1000000,9999999). "\n";
//here the code to make check digits
mycheckdigit($txt);
fwrite($myfile,$myserial);
}
fclose($myfile);
microtime
(gettimeofday()['usec']
)короче:
Y= year
E= part of the EAN or custom code
M= Microtime generated number (gettimeofday()['usec'])
D= random_int() digits
C= Check Digit
YYEEE-MMMMM-MDDDD-DDDCC
Таким образом, у меня есть префикс, который меняется каждый год, я могу узнать, какой бренд является продуктом (поэтому я мог бы использовать только один источник базы данных), и у меня все еще есть достаточные случайные цифры, которые могут быть - возможно, совершенно уникальными, если я считаю, что я будет "собирать" только часть чисел от 1,000,000
и 9,999,999
и разделить ее после использования выше сортировки
Некоторые вопросы для вас:
random_int()
3 цифры короче? Учтите, что я буду генерировать коды ежемесячно, а не ежедневно (но я думаю, что нет больших изменений в уникальности)
- Учитывая, что backend в PHP я думаю использовать функцию
mt_rand()
, может быть хороший подход?
ОБНОВЛЕНИЕ: после предложения @apokryfos, я больше читал о генерации UUID и тому подобное, я нашел хороший компромисс с использованием random_int()
. Потому что мне просто нужны цифры, поэтому хеши HEX не полезны для моих нужд и усложняют ситуацию
Я бы избегал использовать сложные криптографические вещи, такие как ключи RSA и т.д. Мне не нужен такой уровень безопасности и сложности, мне просто нужен способ генерации уникального серийного номера, максимально возможного, насколько это возможно, что нелегко угадать и притупить, если вы не поцарапаете наклейку (так что создание числа не должно делаться от A до Z, но случайным образом)
Вы можете играть с 11 случайными цифрами в год, так что 11-значный номер от 1 до 99999999999 (99,9 миллиарда - намного больше, чем 2 миллиона), так что хватайте комбинаций, я думаю, вы охвачены.
Однако, используя mt_rand
вы, вероятно, столкнетесь с конфликтами. Здесь вы можете спланировать свой путь до 2 миллионов случайных чисел перед использованием базы данных:
<?php
$arr = [];
while (count($arr) < 1000000) {
$num = mt_rand(1, 99999999999);
$numStr = str_pad($num,11,0,STR_PAD_LEFT); //Force 11 digits
if (!isset($arr[$numStr])) {
$arr[$numStr] = true;
}
}
$keys= array_keys($arr);
Количество столкновений, как правило, невелико (первое столкновение происходит примерно на 300 000 - 500 000 чисел, сгенерированных таким образом, что это довольно редко.
Каждое значение в массиве $keys
- это 11-значное число, которое является случайным и уникальным.
Этот подход относительно быстр, но имейте в виду, что ему потребуется довольно много памяти (более 128 МБ).
При этом более широко используемый метод заключается в создании универсально уникального идентификатора (UUID), который, скорее всего, будет уникальным и поэтому не нуждается в проверке на уникальность.
YYrrr
(случайный) вы можете использоватьYYYDDD
(день месяца, 001-365) илиYYcwD
(CalenderWeek 01-52 и dayOfWeek (1-7). Чем больше чисел вы сгенерируете по фиксированному алгоритму, тем ниже вероятность дубликат. В зависимости от вашего (надежного) временного разрешения вы можете перейти к минутам, секундам и даже миллисекундам, что, вероятно, оставляет вам всего несколько цифр - для этого «число» лучше случайного. Вы можете даже добавить некоторые "маскировки", такие как добавление 543 вDDD
, обмен местами и т. д. Интересный вопрос, но, к сожалению, "не по теме" на SO.