├── _config.yml ├── .gitignore ├── composer.json ├── .github └── workflows │ ├── ci.yml │ └── codacy.yml ├── LICENSE ├── src ├── functions.php └── GenerateUuid.php └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | .idea 3 | /composer.lock 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "abmmhasan/uuid", 3 | "description": "UUID (v1, v3-v5) Generator (RFC4122)", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "abmmhasan", 9 | "email": "abmmhasan@gmail.com" 10 | } 11 | ], 12 | "autoload": { 13 | "files": [ 14 | "src/functions.php" 15 | ], 16 | "psr-4": { 17 | "AbmmHasan\\UUID\\": "src/" 18 | } 19 | }, 20 | "minimum-stability": "stable", 21 | "suggest": { 22 | "inforcyph/uid": "If your library uses PHP version 8 or higher, it is recommended to use [infocyph/UID](https://github.com/infocyph/UID) instead." 23 | }, 24 | "require": { 25 | "php": ">=7.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "build" 2 | 3 | on: [ "pull_request", "push" ] 4 | 5 | jobs: 6 | run: 7 | runs-on: ${{ matrix.operating-system }} 8 | strategy: 9 | matrix: 10 | operating-system: [ ubuntu-latest ] 11 | php-versions: [ '7.1','7.2','7.3','7.4','8.0', '8.1' , '8.2' , '8.3' ] 12 | name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Install PHP 18 | uses: shivammathur/setup-php@v2 19 | with: 20 | php-version: ${{ matrix.php-versions }} 21 | 22 | - name: Validate composer.json and composer.lock 23 | run: composer validate --strict 24 | 25 | - name: Install dependencies 26 | run: composer install --prefer-dist --no-progress 27 | 28 | - name: Check PHP Version 29 | run: php -v -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 A. B. M. Mahmudul Hasan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/functions.php: -------------------------------------------------------------------------------- 1 | Note: If your library uses PHP version 8 or higher it is recommended to use [infocyph/UID](https://github.com/infocyph/UID) instead. 15 | 16 | ## Prerequisites 17 | 18 | Language: PHP 7.1/+ 19 | 20 | ## Installation 21 | 22 | ``` 23 | composer require abmmhasan/uuid 24 | ``` 25 | 26 | ## Usage 27 | 28 | ### v1 29 | 30 | ```php 31 | // Get v1 UUID (Time based) 32 | \AbmmHasan\UUID\GenerateUuid::v1(); 33 | 34 | // Get generated node, for further use 35 | $node = \AbmmHasan\UUID\GenerateUuid::getNode(); 36 | 37 | // Pass your pre-generated node (for node specific UUID) 38 | \AbmmHasan\UUID\GenerateUuid::v1($node); 39 | 40 | // alternatively can also use 41 | \AbmmHasan\UUID\uuid1(); 42 | ``` 43 | 44 | ### v3 45 | 46 | ```php 47 | // Get v3 UUID for 'TestString' (default X500 namespace) 48 | \AbmmHasan\UUID\GenerateUuid::v3('TestString'); 49 | 50 | /** 51 | * Get v3 UUID for an URL & pre-defined namespace 52 | * You can pass X500, URL, OID, DNS (check RFC4122 #Appendix C) 53 | */ 54 | \AbmmHasan\UUID\GenerateUuid::v3('abmmhasan.github.io','url'); 55 | 56 | // You can generate a random UUID & use as namespace as well 57 | \AbmmHasan\UUID\GenerateUuid::v3('abmmhasan.github.io','fa1700dd-828c-4d1b-8e6d-a6104807da90'); 58 | 59 | // alternatively can also use 60 | \AbmmHasan\UUID\uuid3(); 61 | ``` 62 | 63 | ### v4 64 | 65 | ```php 66 | // Get v4 UUID (completely random) 67 | \AbmmHasan\UUID\GenerateUuid::v4(); 68 | 69 | // alternatively can also use 70 | \AbmmHasan\UUID\uuid4(); 71 | ``` 72 | 73 | ### v5 74 | 75 | ```php 76 | // Get v5 UUID for 'TestString' (default X500 namespace) 77 | \AbmmHasan\UUID\GenerateUuid::v5('TestString'); 78 | 79 | /** 80 | * Get v5 UUID for an URL & pre-defined namespace 81 | * You can pass X500, URL, OID, DNS (check RFC4122 #Appendix C) 82 | */ 83 | \AbmmHasan\UUID\GenerateUuid::v5('abmmhasan.github.io','url'); 84 | 85 | // You can generate a random UUID & use as namespace as well 86 | \AbmmHasan\UUID\GenerateUuid::v5('abmmhasan.github.io','fa1700dd-828c-4d1b-8e6d-a6104807da90'); 87 | 88 | // alternatively can also use 89 | \AbmmHasan\UUID\uuid5(); 90 | ``` 91 | 92 | ### v2 93 | 94 | ```php 95 | /** 96 | * Not supported! 97 | */ 98 | ``` 99 | 100 | ## Support 101 | 102 | Having trouble? Create an issue! 103 | -------------------------------------------------------------------------------- /src/GenerateUuid.php: -------------------------------------------------------------------------------- 1 | 0, 11 | 'url' => 1, 12 | 'oid' => 2, 13 | 'x500' => 3 14 | ]; 15 | 16 | private static $node; 17 | 18 | /** 19 | * Generates a version 1 UUID. 20 | * 21 | * @param string|null $node The node identifier. Defaults to null. 22 | * @return string 23 | * @throws Exception 24 | */ 25 | public static function v1(string $node = null): string 26 | { 27 | $time = microtime(false); 28 | $time = substr($time, 11) . substr($time, 2, 7); 29 | $time = str_pad(dechex((int)$time + 0x01b21dd213814000), 16, '0', STR_PAD_LEFT); 30 | $clockSeq = random_int(0, 0x3fff); 31 | $node = $node ?? self::getNode(); 32 | return sprintf( 33 | '%08s-%04s-1%03s-%04x-%012s', 34 | substr($time, -8), 35 | substr($time, -12, 4), 36 | substr($time, -15, 3), 37 | $clockSeq | 0x8000, 38 | $node 39 | ); 40 | } 41 | 42 | /** 43 | * Generates the v3 hash for a given string using the specified namespace. 44 | * 45 | * @param string $string The string to generate the hash for. 46 | * @param string $namespace The namespace to use for the hash generation. Defaults to 'x500'. 47 | * @return string 48 | * @throws Exception 49 | */ 50 | public static function v3(string $string, string $namespace = 'x500'): string 51 | { 52 | $namespace = self::nsResolve($namespace); 53 | if (!$namespace) { 54 | throw new Exception('Invalid NameSpace!'); 55 | } 56 | $hash = md5(hex2bin($namespace) . $string); 57 | return self::output(3, $hash); 58 | } 59 | 60 | /** 61 | * Generates a version 4 UUID string. 62 | * 63 | * @return string A version 4 UUID string. 64 | * @throws Exception 65 | */ 66 | public static function v4(): string 67 | { 68 | $string = bin2hex(random_bytes(16)); 69 | return self::output(4, $string); 70 | } 71 | 72 | /** 73 | * Generate a v5 UUID. 74 | * 75 | * @param string $string The string to generate the UUID from. 76 | * @param string $namespace The namespace to use for the UUID generation. Default is 'x500'. 77 | * @return string 78 | * @throws Exception 79 | */ 80 | public static function v5(string $string, string $namespace = 'x500'): string 81 | { 82 | $namespace = self::nsResolve($namespace); 83 | if (!$namespace) { 84 | throw new Exception('Invalid NameSpace!'); 85 | } 86 | $hash = sha1(hex2bin($namespace) . $string); 87 | return self::output(5, $hash); 88 | } 89 | 90 | /** 91 | * Generate a unique hexadecimal node (for v1). 92 | * 93 | * @return string The generated hexadecimal node. 94 | * @throws Exception 95 | */ 96 | public static function getNode(): string 97 | { 98 | if (self::$node) { 99 | return self::$node; 100 | } 101 | return self::$node = sprintf( 102 | '%06x%06x', 103 | random_int(0, 0xffffff) | 0x010000, 104 | random_int(0, 0xffffff) 105 | ); 106 | } 107 | 108 | /** 109 | * Generates a formatted string based on the given version and string. 110 | * 111 | * @param int $version The version number. 112 | * @param string $string The input string. 113 | * @return string The formatted string. 114 | */ 115 | private static function output(int $version, string $string): string 116 | { 117 | $string = str_split($string, 4); 118 | return sprintf( 119 | "%08s-%04s-$version%03s-%04x-%012s", 120 | $string[0] . $string[1], 121 | $string[2], 122 | substr($string[3], 1, 3), 123 | hexdec($string[4]) & 0x3fff | 0x8000, 124 | $string[5] . $string[6] . $string[7] 125 | ); 126 | } 127 | 128 | /** 129 | * Resolves the given namespace. 130 | * 131 | * @param string $namespace The namespace to be resolved. 132 | * @return mixed The resolved namespace or false if it cannot be resolved. 133 | */ 134 | private static function nsResolve(string $namespace) 135 | { 136 | if (self::isValid($namespace)) { 137 | return str_replace('-', '', $namespace); 138 | } 139 | $namespace = str_replace(['namespace', 'ns', '_'], '', strtolower($namespace)); 140 | if (isset(self::$nsList[$namespace])) { 141 | return "6ba7b81" . self::$nsList[$namespace] . "9dad11d180b400c04fd430c8"; 142 | } 143 | return false; 144 | } 145 | 146 | /** 147 | * Check if UUID is valid 148 | * 149 | * @param string $uuid The UUID to be checked 150 | * @return bool 151 | */ 152 | public static function isValid(string $uuid): bool 153 | { 154 | return (bool)preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid); 155 | } 156 | } 157 | --------------------------------------------------------------------------------