├── CHANGELOG.md ├── README.md ├── SECURITY.md ├── composer.json ├── license.txt └── src └── Traits ├── HasNanoidKey.php ├── HasUlidKey.php ├── HasUuidKey.php └── OptiKeyAsPrimary.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [2.1] - 2022-05-26 8 | - Fix HasNanoidKey Traits 9 | 10 | ## [2.0] - 2022-05-20 11 | - Update Laravel 9 support. 12 | - Add support for `nanoid` as key, trait `HasNanoidKey` 13 | - Add optional prefix to key, trait `HasNanoidKey` and `HasUlidKey` 14 | - Change `Str::uuid()` to `Str::orderedUuid()` (timestamp based) 15 | - Change `UuidAsPrimaryKey` trait to `OptiKeyAsPrimary` 16 | - Change `UlidAsPrimaryKey` trait to `OptiKeyAsPrimary` 17 | 18 | ## [1.4] - 2021-01-31 19 | - Fix minimal PHP requirements to ^7.3 | ^8.0 20 | - Change variable `$uuidFieldName` to `$optiKeyFieldName` 21 | - Change variable `$ulidFieldName` to `$optiKeyFieldName` 22 | - Change license from Apache 2.0 to MIT 23 | 24 | ## [1.3] - 2020-12-21 25 | - Update Laravel 8 support. 26 | 27 | ## [1.2] - 2020-03-04 28 | - Add Laravel v7 and lowercase ULID option. 29 | 30 | ## [1.1] - 2020-01-25 31 | - Fix PHP and Laravel requirements 32 | 33 | ## [1.0] - 2020-01-24 34 | - Initial release 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel OptiKey 2 | 3 | [![Build Status](https://travis-ci.com/riipandi/laravel-optikey.svg?branch=master)](https://travis-ci.com/riipandi/laravel-optikey) 4 | [![StyleCI](https://github.styleci.io/repos/235965192/shield?branch=master)](https://github.styleci.io/repos/235965192) 5 | [![Latest Stable Version](http://img.shields.io/packagist/v/riipandi/laravel-optikey.svg?style=flat)](https://packagist.org/packages/riipandi/laravel-optikey) 6 | [![Total Downloads](http://img.shields.io/packagist/dt/riipandi/laravel-optikey.svg?style=flat)](https://packagist.org/packages/riipandi/laravel-optikey) 7 | [![Treeware](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=Treeware&query=%24.total&url=https%3A%2F%2Fpublic.offset.earth%2Fusers%2Ftreeware%2Ftrees)](https://treeware.earth) 8 | 9 | Use UUID, Ulid, or nanoid as optional or primary key in Laravel. 10 | 11 | ```bash 12 | composer require riipandi/laravel-optikey 13 | ``` 14 | 15 | This package adds a very simple trait to automatically generate a UUID, Ulid, or nanoid for your Models. 16 | 17 | ## ✌️ Using as Secondary Key 18 | 19 | ### 1. Update your schemas 20 | 21 | First, you need to add an extra column in your migration. For example: 22 | 23 | ```sh 24 | php artisan make:migration AddOptikeyToUsersTable 25 | ``` 26 | 27 | ```php 28 | // If using UUID for the key 29 | $table->uuid('uid')->after('id')->unique()->index(); 30 | 31 | // If using nanoid or ulid for the key 32 | $table->string('uid')->after('id')->unique()->index(); 33 | ``` 34 | 35 | Sample migration: 36 | 37 | ```php 38 | string('uid', 26)->index()->after('id'); 51 | }); 52 | 53 | // Prefill uid column in users table 54 | Schema::table('users', function (Blueprint $table) { 55 | $results = DB::table('users')->select('id')->get(); 56 | foreach ($results as $result) { 57 | $ulid = \Ulid\Ulid::generate($lowercase = true); // Generate new lowercase Ulid 58 | $generated = 'user_'.$ulid; // this is the generated value with optional prefix 59 | DB::table('users')->where('id', $result->id)->update(['uid' => $generated]); 60 | } 61 | }); 62 | 63 | // Set uid column as unique 64 | Schema::table('users', function (Blueprint $table) { 65 | $table->unique('uid'); 66 | }); 67 | } 68 | 69 | public function down() 70 | { 71 | Schema::table('users', function (Blueprint $table) { 72 | $table->dropColumn('uid'); 73 | }); 74 | } 75 | } 76 | ``` 77 | 78 | ### 2. Add the trait 79 | 80 | Add the trait to your model (pick one between `HasUuidKey`, `HasUlidKey`, or `HasNanoidKey`): 81 | 82 | ```php 83 | first(); 108 | ``` 109 | 110 | Or, using static find method: 111 | 112 | ```php 113 | \App\User::findByOptiKey('xxxxxxxxxxx'); 114 | ``` 115 | 116 | ## ☝️ Using as Primary Key 117 | 118 | You need to change the primary key field type in your migration. For example: 119 | 120 | ```php 121 | $table->uuid('id')->primary(); // for UUID 122 | $table->string('id', 26)->primary(); // for Ulid 123 | $table->string('id', 16)->primary(); // for nanoid 124 | ``` 125 | 126 | Add second trait to use as primary key: 127 | 128 | ```php 129 | 161 | 162 | Copyrights in this project are retained by their contributors. 163 | No copyright assignment is required to contribute to this project. 164 | 165 | [choosealicense]:https://choosealicense.com/licenses/mit/ 166 | 167 | This package is [Treeware](https://treeware.earth). If you use it in production, then we ask that you [**buy the world a tree**](https://plant.treeware.earth/riipandi/laravel-optikey) to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats. 168 | 169 | Please see [license file](./license.txt) for more information. 170 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "riipandi/laravel-optikey", 3 | "description": "Use UUID, Ulid, or nanoid as optional or primary key in Laravel.", 4 | "keywords": [ 5 | "laravel", 6 | "uuid", 7 | "ulid", 8 | "nanoid" 9 | ], 10 | "type": "library", 11 | "require": { 12 | "php": "^7.3|^8.0", 13 | "laravel/framework": "^5.8|^6.0|^7.0|^8.0|^8.1|^9.0|^10.0|^11.0", 14 | "hidehalo/nanoid-php": "^1.1", 15 | "robinvdvleuten/ulid": "^5.0" 16 | }, 17 | "license": "MIT", 18 | "authors": [ 19 | { 20 | "name": "Aris Ripandi", 21 | "email": "aris@ripandi.id" 22 | } 23 | ], 24 | "autoload": { 25 | "psr-4": { 26 | "Riipandi\\LaravelOptiKey\\": "src/" 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "Riipandi\\LaravelOptiKey\\Tests\\": "tests" 32 | } 33 | }, 34 | "require-dev": { 35 | "phpunit/phpunit": ">5.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2022 Aris Ripandi 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/Traits/HasNanoidKey.php: -------------------------------------------------------------------------------- 1 | getOptiKeyFieldName(); 13 | $optiKeyLowerCase = $model->getOptiKeyLowerCase(); 14 | $optiKeyPrefix = $model->getOptiKeyPrefix(); 15 | 16 | if (empty($model->{$optiKeyFieldName})) { 17 | $model->{$optiKeyFieldName} = self::generateId(16, $optiKeyPrefix, $optiKeyLowerCase); 18 | } 19 | }); 20 | } 21 | 22 | public function getOptiKeyFieldName() 23 | { 24 | if (! empty($this->optiKeyFieldName)) { 25 | return $this->optiKeyFieldName; 26 | } 27 | 28 | return 'nanoid'; 29 | } 30 | 31 | public function getOptiKeyLowerCase() 32 | { 33 | if (! empty($this->optiKeyLowerCase)) { 34 | return $this->optiKeyLowerCase; 35 | } 36 | 37 | return false; 38 | } 39 | 40 | public function getOptiKeyPrefix() 41 | { 42 | if (! empty($this->optiKeyPrefix)) { 43 | return $this->optiKeyPrefix; 44 | } 45 | 46 | return ''; 47 | } 48 | 49 | public function scopeByOptiKey($query, $uid) 50 | { 51 | return $query->where($this->getOptiKeyFieldName(), $uid); 52 | } 53 | 54 | public static function findByOptiKey($uid) 55 | { 56 | return static::byOptiKey($uid)->first(); 57 | } 58 | 59 | protected static function generateId($length = 16, $prefix = '', $lowercase = false) 60 | { 61 | $client = new Client(); 62 | $customAlphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 63 | 64 | $uid = $client->formattedId($alphabet = $customAlphabet, $size = $length); 65 | $generated = $prefix ? $prefix.$uid : $uid; 66 | $finalStr = $lowercase == true ? strtolower($generated) : $generated; 67 | 68 | return (string) $finalStr; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Traits/HasUlidKey.php: -------------------------------------------------------------------------------- 1 | getOptiKeyFieldName(); 11 | $optiKeyLowerCase = $model->getOptiKeyLowerCase(); 12 | $optiKeyPrefix = $model->getOptiKeyPrefix(); 13 | 14 | if (empty($model->{$optiKeyFieldName})) { 15 | $model->{$optiKeyFieldName} = self::generateId($optiKeyPrefix, $optiKeyLowerCase); 16 | } 17 | }); 18 | } 19 | 20 | public function getOptiKeyFieldName() 21 | { 22 | if (! empty($this->optiKeyFieldName)) { 23 | return $this->optiKeyFieldName; 24 | } 25 | 26 | return 'ulid'; 27 | } 28 | 29 | public function getOptiKeyLowerCase() 30 | { 31 | if (! empty($this->optiKeyLowerCase)) { 32 | return $this->optiKeyLowerCase; 33 | } 34 | 35 | return false; 36 | } 37 | 38 | public function getOptiKeyPrefix() 39 | { 40 | if (! empty($this->optiKeyPrefix)) { 41 | return $this->optiKeyPrefix; 42 | } 43 | 44 | return ''; 45 | } 46 | 47 | public function scopeByOptiKey($query, $uid) 48 | { 49 | return $query->where($this->getOptiKeyFieldName(), $uid); 50 | } 51 | 52 | public static function findByOptiKey($uid) 53 | { 54 | return static::byOptiKey($uid)->first(); 55 | } 56 | 57 | protected static function generateId($prefix = '', $lowercase = false) 58 | { 59 | $generated = \Ulid\Ulid::generate($lowercase); 60 | 61 | return (string) $prefix ? $prefix.$generated : $generated; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Traits/HasUuidKey.php: -------------------------------------------------------------------------------- 1 | getOptiKeyFieldName(); 13 | 14 | if (empty($model->$optiKeyFieldName)) { 15 | $model->$optiKeyFieldName = self::generateUuid(); 16 | } 17 | }); 18 | } 19 | 20 | public function getOptiKeyFieldName() 21 | { 22 | if (! empty($this->optiKeyFieldName)) { 23 | return $this->optiKeyFieldName; 24 | } 25 | 26 | return 'uuid'; 27 | } 28 | 29 | public static function generateUuid() 30 | { 31 | return (string) Str::orderedUuid(); 32 | } 33 | 34 | public function scopeByOptiKey($query, $uid) 35 | { 36 | return $query->where($this->getOptiKeyFieldName(), $uid); 37 | } 38 | 39 | public static function findByOptiKey($uid) 40 | { 41 | return static::byOptiKey($uid)->first(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Traits/OptiKeyAsPrimary.php: -------------------------------------------------------------------------------- 1 |