Key types
Posts has two independent key-type settings, because there are two different keys and they belong to different owners:
| Config | Axis | What it types | Who owns the model |
|---|---|---|---|
key_type | outbound | author_id — the morph column pointing at your author model | you (your User, Team, …) |
primary_key_type | inbound | the ids of posts, post_categories, post_tags, parent_id and both pivots — the ids other packages point at | this package |
A host with bigint users and uuid posts is an ordinary application, and both default to bigint:
POSTS_KEY_TYPE=uuid # your User model is uuid-keyed
POSTS_PRIMARY_KEY_TYPE=bigint # posts' own ids stay bigintBoth are read when the migration runs, so choose them before migrate. An unrecognised value throws InvalidConfigurationException rather than migrating as bigint, and changing either later is a data migration.
Why primary_key_type defaults to bigint
A post is something other packages point at polymorphically — it is likeable and reportable. A Laravel morph column ($table->morphs('likeable')) is an unsigned bigint, so on a strict engine such as PostgreSQL a uuid post id will not go into one:
SQLSTATE[22P02]: invalid input syntax for type bigint: "019f6f33-22b8-737f-a581-849e7cdc517a"SQLite will not warn you — its type affinity silently stores the string in an integer column, so a green SQLite suite proves nothing here. No foreign key is needed for this to go wrong: a polymorphic column cannot carry one.
Switch primary_key_type only when every morph target in the application shares one key type. With POSTS_PRIMARY_KEY_TYPE=uuid, every other model your likes, reports or comments point at must be uuid-keyed too — a mixed application is not supported. With slug history on uuid or ulid posts, set sluggable.key_type (SLUGGABLE_KEY_TYPE) to the same value before migrating the history table.
On the models
Post, Category and Tag follow primary_key_type through the HasConfigurableKey concern, built on Laravel’s HasUniqueStringIds and switched off on bigint. uuid keys are generated with Str::uuid7(), ulid keys with Str::ulid(), and a malformed id in a route binding is rejected before it reaches the database.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.