├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src ├── AutoIncrement.php ├── AutoIncrementServiceProvider.php ├── Drivers ├── AutoIncrementDriver.php └── MySqlDriver.php └── Facades └── AutoIncrement.php /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | docs 3 | vendor 4 | tests/temp 5 | composer.lock 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 laravelist.com 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel AutoIncrement 2 | 3 | This package will help you set table AUTO_INCREMENT values in your Laravel application. 4 | 5 | ### Why do you need to change auto-increment values? 6 | 7 | If you do not change auto-increment values of your tables you are exposing 8 | how many records you have in there. Imagine some user makes an order and 9 | is redirected to this order detail URL `https://example.com/orders/10`. 10 | User will know then that there are only 10 orders in the whole system which 11 | is probably information you do not want to share. If you will change your 12 | table to start with a higher auto-increment number, for example, 512322, 13 | it will not be that obvious (`https://example.com/orders/512332`). 14 | 15 | But what if he makes another order month from now? There will be only small 16 | difference between these numbers and anyone can easily calculate your monthly 17 | activity. There is an easy solution for this. Add auto-increment update 18 | toLaravel's command scheduler and add some random number to your next auto-increment id 19 | automatically on hourly, daily, monthly, etc., basis. 20 | 21 | ### What are the benefits? 22 | 23 | * Integer values are way more efficient than UUIDs or other types of string ids 24 | 25 | * Sorting by id still leads to chronological order 26 | 27 | * You do not expose the total number of resources in your database, for example `https://example.com/users/10` 28 | 29 | ## Installation 30 | 31 | You can install this package via composer using this command: 32 | 33 | ``` bash 34 | composer require rorecek/laravel-autoincrement 35 | ``` 36 | 37 | ## Usage 38 | 39 | You can use this package to set the next auto-increment id to a specific value, 40 | or to add a number to current value or to reset auto-increment to the lowest 41 | possible value. 42 | 43 | ``` php 44 | AutoIncrement::table('items')->set(100); 45 | // Set table auto-increment value to 100 46 | 47 | AutoIncrement::table('items')->add(500); 48 | // Increase current auto-increment value by 500 49 | 50 | AutoIncrement::table('items')->addRandomBetween(10, 100); 51 | // Increase current auto-increment value by random number between 10 and 100 52 | 53 | AutoIncrement::table('items')->reset(); 54 | // Reset auto-increment to the lowest value possible taking existing records in consideration. 55 | ``` 56 | 57 | ### Migrations 58 | 59 | Set auto-increments directly in your migrations. 60 | 61 | ``` php 62 | Schema::create('items', function (Blueprint $table) { 63 | $table->bigIncrements('id'); 64 | $table->timestamps(); 65 | }); 66 | 67 | AutoIncrement::table('items')->set(101); 68 | // Next auto-increment id will be 101 69 | ``` 70 | 71 | ### Scheduler 72 | 73 | Setup automatic auto-increment increases using task scheduler. 74 | 75 | ``` php 76 | // App\Console\Kernel.php 77 | 78 | protected function schedule(Schedule $schedule) 79 | { 80 | $schedule->call(function () { 81 | AutoIncrement::table('messages')->add(35); 82 | })->hourly(); 83 | 84 | $schedule->call(function () { 85 | AutoIncrement::table('registrations')->addRandomBetween(10, 100); 86 | AutoIncrement::table('bookings')->addRandomBetween(100, 500); 87 | })->daily(); 88 | } 89 | ``` 90 | 91 | ## Advanced usage 92 | 93 | You can optionally use different connections and/or closures if needed. 94 | 95 | ``` php 96 | AutoIncrement::connection('foo')->table('items')->... 97 | // Using different connection 98 | 99 | AutoIncrement::table('items')->set(function () { 100 | return (int) date('ymd') . 1001; 101 | }); 102 | // Using closure 103 | ``` 104 | 105 | ## Support 106 | 107 | If you believe you have found an issue, please report it using the [GitHub issue tracker](https://github.com/rorecek/laravel-ulid/issues), or better yet, fork the repository and submit a pull request. 108 | 109 | If you're using this package, I'd love to hear your thoughts. Thanks! 110 | 111 | ## License 112 | 113 | The MIT License (MIT). [Pavel Rorecek](https://laravelist.com) 114 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rorecek/laravel-autoincrement", 3 | "description": "Set table AUTO_INCREMENT values in your Laravel application", 4 | "keywords": ["laravel", "mysql", "autoincrement", "auto-increment", "auto_increment", "id"], 5 | "homepage": "https://github.com/rorecek/laravel-autoincrement", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Pavel Rorecek", 10 | "email": "info@laravelist.com", 11 | "homepage": "https://laravelist.com", 12 | "role": "Developer" 13 | } 14 | ], 15 | "require": { 16 | "php" : "^7.1|^8.0", 17 | "laravel/framework": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Rorecek\\AutoIncrement\\": "src" 22 | } 23 | }, 24 | "config": { 25 | "sort-packages": true 26 | }, 27 | "extra": { 28 | "laravel": { 29 | "providers": [ 30 | "Rorecek\\AutoIncrement\\AutoIncrementServiceProvider" 31 | ], 32 | "aliases": { 33 | "AutoIncrement": "Rorecek\\AutoIncrement\\Facades\\AutoIncrement" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/AutoIncrement.php: -------------------------------------------------------------------------------- 1 | connection(); 28 | } 29 | 30 | public function connection($connection = 'mysql'): AutoIncrement 31 | { 32 | $this->connection = $connection; 33 | 34 | $driver = config("database.connections.$connection.driver"); 35 | 36 | if ($driver === 'mysql') { 37 | $this->driver = new MySqlDriver($connection); 38 | } else { 39 | throw new \RuntimeException("There is no AutoIncrement driver for connection: $connection"); 40 | } 41 | 42 | return $this; 43 | } 44 | 45 | public function table($name): AutoIncrement 46 | { 47 | throw_unless( 48 | $this->driver->hasTable($name), 49 | \RuntimeException::class, 50 | 'There is no table: ' . $name 51 | ); 52 | 53 | $this->table = $name; 54 | 55 | return $this; 56 | } 57 | 58 | public function addRandomBetween(int $min, int $max): bool 59 | { 60 | return $this->add(random_int($min, $max)); 61 | } 62 | 63 | public function add($value): bool 64 | { 65 | return $this->set($this->get() + $this->parseValue($value)); 66 | } 67 | 68 | public function set($value, $primaryKey = 'id'): bool 69 | { 70 | $id = $this->parseValue($value); 71 | 72 | throw_if($id < 1, \RuntimeException::class, 'Auto-increment value must be positive'); 73 | throw_if( 74 | $id < $this->minAllowedValue($primaryKey), 75 | \RuntimeException::class, 76 | 'Auto-increment value must be equal or greater than ' . $this->minAllowedValue($primaryKey) 77 | ); 78 | 79 | return $this->driver->set($this->getTable(), $id); 80 | } 81 | 82 | protected function parseValue($value): int 83 | { 84 | if ($value instanceof \Closure) { 85 | return $value(); 86 | } 87 | 88 | if (is_array($value)) { 89 | return $value[array_rand($value)]; 90 | } 91 | 92 | return $value; 93 | } 94 | 95 | protected function minAllowedValue($primaryKey = 'id'): int 96 | { 97 | return $this->driver->maxValue($this->getTable(), $primaryKey) + 1; 98 | } 99 | 100 | protected function getTable(): string 101 | { 102 | throw_unless( 103 | $this->table, 104 | \RuntimeException::class, 105 | 'No table selected. You have to use table() method.' 106 | ); 107 | 108 | return $this->table; 109 | } 110 | 111 | public function get(): int 112 | { 113 | return $this->driver->get($this->getTable()); 114 | } 115 | 116 | public function reset($primaryKey = 'id'): bool 117 | { 118 | return $this->set($this->minAllowedValue($primaryKey)); 119 | } 120 | 121 | public function getDriver(): AutoIncrementDriver 122 | { 123 | return $this->driver; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/AutoIncrementServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(AutoIncrement::class); 17 | $this->app->alias(AutoIncrement::class, 'auto-increment'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Drivers/AutoIncrementDriver.php: -------------------------------------------------------------------------------- 1 | connection = $connection; 15 | $this->database = config("database.connections.$connection.database"); 16 | } 17 | 18 | public function get($table): int 19 | { 20 | $result = DB::connection($this->connection) 21 | ->select( 22 | 'SELECT AUTO_INCREMENT FROM information_schema.TABLES' 23 | . ' WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?', 24 | [$this->database, $table] 25 | ); 26 | 27 | if (isset($result[0], $result[0]->AUTO_INCREMENT)) { 28 | return $result[0]->AUTO_INCREMENT; 29 | } 30 | 31 | throw new \RuntimeException("Can't get auto-increment value for table: " . $table); 32 | } 33 | 34 | public function maxValue($table, $primaryKey = 'id'): int 35 | { 36 | return (int) DB::connection($this->connection)->table($table)->max($primaryKey); 37 | 38 | } 39 | 40 | public function set($table, $value): bool 41 | { 42 | return DB::connection($this->connection)->statement("ALTER TABLE $table AUTO_INCREMENT=$value"); 43 | } 44 | 45 | public function hasTable($table): bool 46 | { 47 | return DB::connection($this->connection)->getSchemaBuilder()->hasTable($table); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Facades/AutoIncrement.php: -------------------------------------------------------------------------------- 1 |