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

Open source

Connections for Laravel

Install
composer require roundly-consulting/connections-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

Many-to-many connections between Eloquent models, with per-connection permissions and optional expirations. Connect any model to any other — a user to a team, an organization to a project — record what each connection is allowed to do, walk it through a pending → accepted / blocked invitation flow, and let expired connections prune themselves. A fluent Connections facade, trait verbs, standalone actions, events, an opt-in Gate hook and a test fake keep every operation to one readable line. MIT-licensed, with no third-party runtime dependencies beyond Laravel and two small Roundly helper packages.

What you get

Connect any model to any model

One polymorphic, directed connection per pair — a user to a team, an organization to a project. Re-connecting only changes what you pass.

Per-connection permissions

Grant, revoke, sync and clear permission sets; check one, any or all of them, with * and posts.* wildcards.

Invitations & status

Pending → accepted / blocked flows with enforced status transitions and events at every step. Only active connections grant access.

Expirations

expiresIn(), extend() and a default expiry window, plus a prune command and an expiring-soon event.

Bulk operations & sync

toMany()->connectAll() and friends, and from()->sync() reconciling an exact set into a typed SyncResult.

Facade, DI or actions

One Connections facade, an injectable ConnectionManager or single-purpose actions — plus nine lifecycle events and an opt-in Gate::before hook.

Test fake

Connections::fake() records facade, injected-manager and trait writes for assertions while still writing to your test database.

Documentation

Installation

Install via Composer, publish and run the migration, and optionally publish the config file.

Configuration

Every config key and its default — model, table, key type, cache, events, Gate, default permissions, status and expiry.

Database schema

One polymorphic connections table — morph keys, jsonb permissions and meta, status, expiry, soft deletes and a unique pair index.

Connectable models

Add the HasConnections trait and Connectable contract to any model, scaffold with make:connectable, and use the trait verbs.

The Connections facade

The whole public API in one facade — between() and from() builders, the permissions() sub-accessor, expiring(), prune(), flushCache() and fake().

DI and actions

Inject ConnectionManager instead of the facade, or run single-purpose actions — with the full facade-to-action map, DTOs and exceptions.

Permissions

Grant, revoke, sync and clear per-connection permissions; check one, any or all of them, with * and segment wildcards.

Invitations & status

Model approval flows: create pending connections, accept or block them from either side, and use the ConnectionStatus enum helpers.

Expirations

Give connections an expiry, move or clear it, set a default window, and see how expiry affects access checks.

Metadata

Attach free-form context to a connection in a JSON meta bag, read it with dot access, and merge or replace it on re-connect.

Bulk operations & sync

Connect, disconnect, grant and revoke across many connectables at once, or reconcile an exact set with from()->sync().

Toggle, reconnect & restore

Disconnect with soft deletes, flip a connection with toggle(), and bring a removed one back as it was with reconnect() or fresh with connect().

Querying connections

Check who is connected, walk both directions, filter with active, expired, expiring and permission scopes, and fetch typed models.

Events

Nine lifecycle events for creates, updates, removals, permission changes, invitations, status changes, restores and expiry warnings.

Gate integration

Opt in to a Gate::before hook so $user->can('publish', $team) and Laravel’s other authorization checks resolve through connections.

Caching

Permission checks are memoised per connector–connectable pair, invalidated on every package write, and bypassable with force: true.

Artisan commands

Prune expired connections, dispatch expiring-soon events, scaffold connectable models, and schedule the maintenance.

Custom connection model

Swap in your own Connection subclass via connections.model to add behaviour, and wire optional integrations such as reports-for-laravel.

Testing

Record every write with Connections::fake() — facade, injected manager and trait — assert each operation, and seed rows with the factory.

Requirements

PHP 8.4+, Laravel 12 or 13, and two Roundly helper packages that Composer installs automatically.

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.