mirror of
https://github.com/ramsey/uuid.git
synced 2026-06-15 16:07:55 +03:00
153 lines
5.7 KiB
ReStructuredText
153 lines
5.7 KiB
ReStructuredText
.. _nonstandard.guid:
|
|
|
|
===================================
|
|
Globally Unique Identifiers (GUIDs)
|
|
===================================
|
|
|
|
.. tip::
|
|
|
|
Using these techniques to work with GUIDs is useful if you're working with
|
|
identifiers that have been stored in GUID byte order. For example, this is
|
|
the case if working with the ``UNIQUEIDENTIFIER`` data type in Microsoft SQL
|
|
Server. This is a GUID, stored as a 16-byte binary string. If working
|
|
directly with the bytes, you may use the GUID functionality in ramsey/uuid
|
|
to properly handle this data type.
|
|
|
|
According to the Windows Dev Center article on `GUID structure`_, "GUIDs are the
|
|
Microsoft implementation of the distributed computing environment (DCE)
|
|
universally unique identifier." For all intents and purposes, a GUID string
|
|
representation is identical to that of an `RFC 4122`_ UUID. For historical
|
|
reasons, *the byte order is not*.
|
|
|
|
The `.NET Framework documentation`_ explains:
|
|
|
|
Note that the order of bytes in the returned byte array is different from
|
|
the string representation of a Guid value. The order of the beginning
|
|
four-byte group and the next two two-byte groups is reversed, whereas the
|
|
order of the last two-byte group and the closing six-byte group is the same.
|
|
|
|
This is best explained by example.
|
|
|
|
.. code-block:: php
|
|
:caption: Decoding a GUID from byte representation
|
|
:name: nonstandard.guid.decode-bytes-example
|
|
|
|
use Ramsey\Uuid\FeatureSet;
|
|
use Ramsey\Uuid\UuidFactory;
|
|
|
|
// The bytes of a GUID previously stored in some datastore.
|
|
$guidBytes = hex2bin('0eab93fc9ec9584b975e9c5e68c53624');
|
|
|
|
$useGuids = true;
|
|
$featureSet = new FeatureSet($useGuids);
|
|
$factory = new UuidFactory($featureSet);
|
|
|
|
$guid = $factory->fromBytes($guidBytes);
|
|
|
|
printf(
|
|
"Class: %s\nGUID: %s\nVersion: %d\nBytes: %s\n",
|
|
get_class($guid),
|
|
$guid->toString(),
|
|
$guid->getFields()->getVersion(),
|
|
bin2hex($guid->getBytes())
|
|
);
|
|
|
|
This transforms the bytes of a GUID, as represented by ``$guidBytes``, into a
|
|
:php:class:`Ramsey\\Uuid\\Guid\\Guid` instance and prints out some details about
|
|
it. It looks something like this:
|
|
|
|
.. code-block:: text
|
|
|
|
Class: Ramsey\Uuid\Guid\Guid
|
|
GUID: fc93ab0e-c99e-4b58-975e-9c5e68c53624
|
|
Version: 4
|
|
Bytes: 0eab93fc9ec9584b975e9c5e68c53624
|
|
|
|
Note the difference between the string GUID and the bytes. The bytes are
|
|
arranged like this:
|
|
|
|
.. code-block:: text
|
|
|
|
0e ab 93 fc 9e c9 58 4b 97 5e 9c 5e 68 c5 36 24
|
|
|
|
In an `RFC 4122`_ UUID, the bytes are stored in the same order as you see
|
|
presented in the string representation. This is often called *network byte
|
|
order*, or *big-endian* order. In a GUID, the order of the bytes are reversed
|
|
in each grouping for the first 64 bits and stored in *little-endian* order. The
|
|
remaining 64 bits are stored in network byte order. See `Endianness
|
|
<#nonstandard-guid-endianness>`_ to learn more.
|
|
|
|
.. caution::
|
|
|
|
The bytes themselves do not indicate their order. If you decode GUID bytes
|
|
as a UUID or UUID bytes as a GUID, you will get the wrong values. However,
|
|
you can always create a GUID or UUID from the same string value; the bytes
|
|
for each will be in a different order, even though the string is the same.
|
|
|
|
The key is to know ahead of time in what order the bytes are stored. Then,
|
|
you will be able to decode them using the correct approach.
|
|
|
|
|
|
Converting GUIDs to UUIDs
|
|
#########################
|
|
|
|
Continuing from the example, :ref:`nonstandard.guid.decode-bytes-example`, we
|
|
can take the GUID string representation and convert it into a standard UUID.
|
|
|
|
.. code-block:: php
|
|
:caption: Convert a GUID to a UUID
|
|
:name: nonstandard.guid.convert-example
|
|
|
|
$uuid = Uuid::fromString($guid->toString());
|
|
|
|
printf(
|
|
"Class: %s\nUUID: %s\nVersion: %d\nBytes: %s\n",
|
|
get_class($uuid),
|
|
$uuid->toString(),
|
|
$uuid->getFields()->getVersion(),
|
|
bin2hex($uuid->getBytes())
|
|
);
|
|
|
|
Because the GUID was a version 4, random UUID, this creates an instance of
|
|
:php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV4` from the GUID string and prints out a
|
|
few details about it. It looks something like this:
|
|
|
|
.. code-block:: text
|
|
|
|
Class: Ramsey\Uuid\Rfc4122\UuidV4
|
|
UUID: fc93ab0e-c99e-4b58-975e-9c5e68c53624
|
|
Version: 4
|
|
Bytes: fc93ab0ec99e4b58975e9c5e68c53624
|
|
|
|
Note how the UUID string is identical to the GUID string. However, the byte
|
|
order is different, since they are in big-endian order. The bytes are now
|
|
arranged like this:
|
|
|
|
.. code-block:: text
|
|
|
|
fc 93 ab 0e c9 9e 4b 58 97 5e 9c 5e 68 c5 36 24
|
|
|
|
|
|
.. admonition:: Endianness
|
|
:name: nonstandard.guid.endianness
|
|
|
|
Big-endian and little-endian refer to the ordering of bytes in a multi-byte
|
|
number. Big-endian order places the most significant byte first, followed by
|
|
the other bytes in descending order. Little-endian order places the least
|
|
significant byte first, followed by the other bytes in ascending order.
|
|
|
|
Take the hexadecimal number ``0x1234``, for example. In big-endian order,
|
|
the bytes are stored as ``12 34``, and in little-endian order, they are
|
|
stored as ``34 12``. In either case, the number is still ``0x1234``.
|
|
|
|
Networking protocols usually use big-endian ordering, while computer
|
|
processor architectures often use little-endian ordering.
|
|
The terms originated in Jonathan Swift's *Gulliver's Travels*, where the
|
|
Lilliputians argue over which end of a hard-boiled egg is the best end to
|
|
crack.
|
|
|
|
|
|
.. _GUID structure: https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid#remarks
|
|
.. _RFC 4122: https://tools.ietf.org/html/rfc4122
|
|
.. _.NET Framework documentation: https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray#remarks
|