What exactly are you doing? What errors are you getting, if any, what database are you using, and what messages or logs are being produced? You shouldn't have to do much to switch to UUIDs if you really want to.
What I did when using UUIDs was adding the HasUuids Eloquent Concern, change the migrations to use $table->uuid('id')->primary->default(DB::raw('the_database_method()')) and $table->foreignUuid('something_id')->constrained('something')->cascadeOnDelete(), add those relationships in models, and generate the UUID with a raw database method.
There's nothing else you must do unless you're also dealing with starter kits and need to modify the migrations, maybe add your PersonalAccessToken if using Sanctum and put this in your AppServiceProvider's boot method. See for example: https://dev.to/adnanbabakan/implement-uuid-primary-key-in-laravel-and-its-benefits-55o3. Not everything in here is required, but it's a decent guide.
In migrations, this example is for Postgres, MySQL and others do it differently:
$table->uuid('id')->primary()->default(DB::raw('gen_random_uuid()'));
In your model, for example:
// Add related models and imports
use App\Models\Post;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable, HasUuids; // HasUuids
// For example...
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
In something related, in a migration:
$table->uuid('id')->primary()->default(DB::raw('gen_random_uuid()'));
$table->string('title');
$table->string('description');
$table->string('slug');
$table->text('content');
$table->foreignUuid('user_id')->constrained('users')->cascadeOnDelete();
$table->timestamps();
In related Model, for example:
namespace App\Models;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\User;
class Post extends Model
{
//
use HasUuids, HasFactory;
protected $fillable = [
'user_id',
'title',
'description',
'slug',
'content',
];
protected $casts = [];
protected $hidden = [];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Example routes:
use App\Models\Post;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
use App\Http\Controllers\UserController;
// Loop over posts in welcome page
Route::get('/', function () {
$posts = Post::with('user')->get();
return view('welcome', ['posts' => $posts]);
});
// Specific routes to users and posts
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');
Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show');
// You can also do this:
Route::get('/posts/{id}', [PostController::class, 'showByUuid']);
// Or this:
Route::get('/posts/{id}', function (string $id) {
// ...
})->whereUuid('id');
// Or this:
Route::get('/posts/{id}', function (Request $request, string $id) {
//
});
Use .env.testing for example:
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=testdb
DB_USERNAME=james
DB_PASSWORD=james
Create the database and make sure the user specified can do things with it.
APP_ENV=testing php artisan migrate
And run:
APP_ENV=testing php artisan serve
And that's all you have to do. You don't need $keyType = 'string'; or $incrementing = false; because Laravel is smart enough to know this from $table->uuid().
Putting uuids on models behind serial id types for public routes as Tray2 said is an option, for example if you don't want to expose incrementing id's in a simple ReST API or in any other public route. Index them in that case, make them a bit more suitable for indexing with uuid v7 types which are time ordered, almost sequential, and index locality problems are taken care of. You can add a loadByUuid() method on the models or similar. If you do that, you can also add them using the Str::uuid or a better one that generates time ordered v7 uuids after the model has booted, so if the uuid doesn't exist, make one and assign it.