Database schema
Every connection is one row in a single polymorphic table — connections by default, renamed via the table key. The published migration, abridged:
Schema::create('connections', function (Blueprint $table) use ($keyType): void {
$table->id();
$table->morphKey('connector', $keyType, nullable: false);
$table->morphKey('connectable', $keyType, nullable: false);
$table->jsonb('permissions');
$table->string('status')->default('accepted')->index();
$table->jsonb('meta')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
$table->softDeletes();
$table->unique(
['connector_type', 'connector_id', 'connectable_type', 'connectable_id'],
'connections_morph_unique',
);
});| Column | Type | Notes |
|---|---|---|
id | bigint | Primary key. |
connector_type / connector_id | morph key | The side that initiated the connection. The id follows key_type. |
connectable_type / connectable_id | morph key | The side the connection points to. The id follows key_type. |
permissions | jsonb | Permission strings; cast to a Collection. |
status | string, indexed | pending, accepted or blocked; defaults to accepted. Cast to ConnectionStatus. |
meta | jsonb, nullable | Free-form metadata; cast to an array. |
expires_at | timestamp, nullable | Null means the connection never expires. |
created_at / updated_at | timestamps | Standard Eloquent timestamps. |
deleted_at | soft deletes | Set by disconnect(), sync detaches and connections:prune; cleared again when the pair is revived or restored. |
UUID and ULID keys
Both morph id columns follow key_type — bigint (the default), uuid or ulid. Set it before publishing and running the migration: it is fixed once the table exists, and the bigint default produces exactly the columns of Laravel’s own morphs().
# .env — set before publishing and running the migration
CONNECTIONS_KEY_TYPE=ulid
php artisan vendor:publish --tag="connections-migrations"
php artisan migrateOne row per pair
The connections_morph_unique index covers connector_type, connector_id, connectable_type and connectable_id — soft-deleted rows included. Connecting the same pair again updates the existing row instead of adding a second one, and a disconnected or pruned pair is revived in place — connect() starts it fresh, reconnect() restores it as it was (see Toggle, reconnect & restore).
permissions and meta are jsonb columns. On PostgreSQL that makes them comparable and indexable; on MySQL and SQLite the schema builder compiles them to the same type as json.
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.