NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Attach free-form context — who invited whom, a role label, an import source — to a connection’s JSON meta column, with no side table to maintain:

Connections::between($user, $team)
    ->withMeta(['invited_by' => $admin->id, 'role' => ['label' => 'owner']])
    ->connect();

$connection->meta('role.label');           // 'owner' (dot access)
$connection->meta('missing', 'fallback');  // 'fallback'

// Re-connecting merges meta by default; replaceMeta() overwrites instead.
Connections::between($user, $team)->withMeta(['note' => 'hi'])->connect();          // merge; perms + expiry kept
Connections::between($user, $team)->withMeta(['note' => 'hi'])->replaceMeta()->connect();

// The trait verb takes meta too.
$user->connectTo($team, ['view'], now()->addMonth(), ['source' => 'import']);
  • meta($key, $default) reads with dot notation and returns the default when the key is missing.
  • Re-connecting merges the staged meta over the stored meta at the top level — permissions and expiry are kept; replaceMeta() overwrites the meta instead.
  • A connect() without withMeta() leaves the stored meta untouched.
  • withMeta() can be called several times on one builder — each call merges into the staged bag.
  • connectAll() and SyncTarget items passed to sync() accept meta too.
  • The raw meta attribute is the full array, or null when nothing was stored.

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 crypto

By 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.