PHP / MySQL: хранение и получение UUIDS - PullRequest
7 голосов
/ 15 мая 2010

Я пытаюсь добавить UUID в пару таблиц, но я не уверен, каким будет лучший способ их хранения / извлечения. Я понимаю, что гораздо эффективнее использовать BINARY (16) вместо VARCHAR (36). Проведя небольшое исследование, я также обнаружил, что вы можете преобразовать строку UUID в двоичный файл с помощью:

 UNHEX(REPLACE(UUID(),'-',''))

Прошу прощения за мое невежество, но есть ли простой способ сделать это с помощью PHP, а затем, при необходимости, превратить его в строку для удобства чтения?

Кроме того, будет ли иметь большое значение, если я использую это как первичный ключ вместо auto_increment?

EDIT:

Найдена часть ответа:

 $bin = pack("h*", str_replace('-', '', $guid));

Как бы вы распаковали его?

Ответы [ 3 ]

11 голосов
/ 15 мая 2010

Хорошо - постараюсь ответить на мой собственный вопрос.Это лучшее, что я мог придумать:

Упаковка:

$binary =  pack("h*", str_replace('-', '', $string));

Распаковка

$string = unpack("h*", $binary);
$string = preg_replace("/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/", "$1-$2-$3-$4-$5", $string);

Есть ли какие-либо проблемы с этим, кто-нибудь может увидеть?

2 голосов
/ 19 ноября 2018

Для php> = 5.4 мы можем использовать hex2bin и bin2hex :

$binary = hex2bin(str_replace('-', '', $value));


$string = bin2hex($value);
$string = preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);

Или используйте функцию для большей организации:

function uuid2bin($uuid) {
   return hex2bin(str_replace('-', '', $uuid));
}

function bin2uuid($value) {
   $string = bin2hex($value);

   return preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);
}

Для Laravel (используя поле ID):

public function setIdAttribute($value)
{
   $this->attributes[ 'id' ] = hex2bin(str_replace('-', '', $value));
}

public function getIdAttribute($value)
{
   $string = bin2hex($value);

   return preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);
}
2 голосов
/ 31 августа 2018

Как упомянул @Johan, вам нужно использовать заглавную H (шестнадцатеричная строка, сначала большой клев) , чтобы быть совместимым с функциями MySQL HEX / UNHEX

function uuid_to_bin($uuid){
  return pack("H*", str_replace('-', '', $uuid));
}

Более компактное декодирование обратно в функцию UUID с использованием только методов unpack() и join(). Внимание: Вам необходимо назвать параметры / ключи распакованного массива, чтобы не перезаписывать !

function bin_to_uuid($bin){
  return join("-", unpack("H8time_low/H4time_mid/H4time_hi/H4clock_seq_hi/H12clock_seq_low", $bin));
}

А для более старых версий MySQL, где отсутствуют функции uuid_to_bin() и bin_to_uuid():

DELIMITER $$
CREATE FUNCTION `fn_uuid_to_bin`(`s` CHAR(36)) RETURNS binary(16)
    DETERMINISTIC

RETURN UNHEX(REPLACE(s, '-', ''))$$

DELIMITER ;

DELIMITER $$
CREATE FUNCTION `fn_bin_to_uuid`(`b` BINARY(16)) RETURNS char(36) CHARSET utf8mb4
    DETERMINISTIC
BEGIN
  DECLARE hex CHAR(32);
  SET hex = HEX(b);
  RETURN LOWER(CONCAT(LEFT(hex, 8), '-', MID(hex, 9,4), '-', MID(hex, 13,4), '-', MID(hex, 17,4), '-', RIGHT(hex, 12)));
END$$

DELIMITER ;
...