---
title: "The Connections facade — Connections for Laravel | Roundly"
description: "The whole public API in one facade — between() and from() builders, the permissions() sub-accessor, expiring(), prune(), flushCache() and fake()."
url: https://roundly-consulting.com/open-source/docs/connections-for-laravel/connections-facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Connections for Laravel](https://roundly-consulting.com/open-source/docs/connections-for-laravel.md)

# The Connections facade

The Connections facade is the package’s public API — every operation is reachable from it, and it is the recommended way in. Its root is RoundlyConsulting\\Connections\\ConnectionManager, a container singleton, and the HasConnections trait verbs delegate to the same manager (see DI and actions for the other entry points):

| Method | Returns | Purpose |
| --- | --- | --- |
| `Connections::between($connector, $connectable)` | `PendingConnection` | Fluent builder for one pair. |
| `Connections::from($connector)` | `PendingConnection` | Builder with the connectable set later (to(), toMany()) or a sync() reconcile. |
| `Connections::expiring(int $days = 7)` | `Builder<Connection>` | Every live connection expiring within the window, across all connectors. |
| `Connections::prune()` | `int` | Soft-delete expired connections, returning the count. |
| `Connections::flushCache()` | `void` | Drop the in-request permission cache. |
| `Connections::fake()` | `ConnectionFake` | Recording fake for tests — see Testing. |

between() starts a builder for a pair; from() starts one for a connector and defers the connectable to to():

```php
use RoundlyConsulting\Connections\DataTransferObjects\SyncTarget;
use RoundlyConsulting\Connections\Facades\Connections;

// Create the connection, or update the pair's existing one, with permissions and an expiry.
Connections::between($user, $team)
    ->withPermissions('view', 'edit')
    ->expiresIn(now()->addMonth())   // CarbonInterface, CarbonInterval, or seconds
    ->connect();

// Defer the connectable until later with from()->to().
Connections::from($user)->to($team)->withPermissions('view')->connect();

// Move the expiry, or clear it with null.
Connections::between($user, $team)->extend(now()->addYear());
Connections::between($user, $team)->extend(null);

// Look the pair up.
Connections::between($user, $team)->exists();   // bool — an active connection exists
Connections::between($user, $team)->find();     // ?Connection — in any status

// Remove the connection (soft delete).
Connections::between($user, $team)->disconnect();

// Reconcile a connector to exactly this set (connect missing, disconnect extras).
Connections::from($user)->sync([$teamA, new SyncTarget($teamB, permissions: ['read'])]); // SyncResult

// Connections expiring within 14 days, across every connector.
Connections::expiring(14)->with('connector')->get();

// Remove all expired connections, returning how many were removed.
$removed = Connections::prune();

// Drop the in-request permission cache mid-request (it already resets per request / job).
Connections::flushCache();
```

The cache is invalidated automatically on every write, so a check after a write reflects the change without any force flag.

## Staging the connection

Modifiers stage state on the builder; nothing is written until a terminal verb runs:

```php
use Carbon\CarbonInterval;
use RoundlyConsulting\Connections\Facades\Connections;

$connection = Connections::from($user)
    ->to($team)                              // the connectable (or start with between())
    ->withPermissions('view', 'edit')        // staged permissions, de-duplicated
    ->withPermissions('publish')             // repeated calls add to the staged set
    ->expiresIn(CarbonInterval::days(30))    // CarbonInterface, CarbonInterval or seconds
    ->withMeta(['source' => 'signup'])       // merged into the meta bag
    ->connect();                             // terminal verb: returns the Connection
```

- to($connectable) — set the connectable when the builder started with from().
- toMany($connectables) — stage several connectables for the bulk verbs (see Bulk operations & sync).
- withPermissions(...$permissions) — stage permissions; repeated calls add to the set, duplicates are dropped.
- expiresIn($value) — a CarbonInterface instant, a CarbonInterval from now, or an integer of seconds from now.
- expiringAt(?$instant) — an exact expiry instant, or null for none.
- withMeta($array) / replaceMeta() — stage metadata; merged into the stored meta unless replaceMeta() is called.
- asPending() — create the connection in the pending state; invite() is sugar for asPending()->connect().

## Terminal verbs

| Verb | Returns | Does |
| --- | --- | --- |
| `connect()` | `Connection` | Create the pair, or change only what is staged on its existing connection; revives a soft-deleted pair. |
| `invite()` | `Connection` | connect() in the pending state; throws InvalidStatusTransition over an accepted or blocked connection. |
| `accept() / block()` | `Connection` | Change the status; throw ConnectionNotFound when there is no connection. accept() is the only way to lift a block. |
| `disconnect()` | `void` | Soft-delete; throws ConnectionNotFound when there is no connection. |
| `toggle()` | `?Connection` | Disconnect an active connection (returns null), otherwise connect — never lifting a block or renewing an expiry. |
| `reconnect() / restore()` | `Connection` | Restore the soft-deleted connection with its permissions, expiry and meta, or connect afresh. |
| `permissions()` | `ConnectionPermissions` | The pair’s permission set: grant, revoke, sync, clear, all, has, hasAny, hasAll — see Permissions. |
| `extend(?$expiresAt)` | `Connection` | Move or clear the expiry; throws ConnectionNotFound. |
| `exists()` | `bool` | Whether the pair is connected (active only, while enforce\_active\_on\_check is on). |
| `find()` | `?Connection` | The pair’s connection in any status, or null when there is none (or it is soft-deleted). |
| `sync($connectables)` | `SyncResult` | Reconcile the connector to exactly this set of Connectable or SyncTarget items — see Bulk operations & sync. |
| `connectAll() / grantAll() / revokeAll()` | `Collection` | Bulk verbs over the toMany() targets. |
| `disconnectAll()` | `void` | Bulk disconnect over the toMany() targets. |

## The permissions() sub-accessor

between()->permissions() is the permission set of one connection — grant(), revoke(), sync() and clear() write it; all(), has(), hasAny() and hasAll() read it (see Permissions):

```php
use RoundlyConsulting\Connections\Facades\Connections;

$permissions = Connections::between($user, $team)->permissions();

$permissions->grant('publish');          // Connection — creates the connection if absent
$permissions->revoke('publish');         // Connection — throws ConnectionNotFound if absent
$permissions->sync('view', 'edit');      // Connection — exact set, creates if absent
$permissions->clear();                   // Connection — remove every permission; throws ConnectionNotFound if absent

$permissions->all();                     // Collection<int, string> — what is stored
$permissions->has('edit');               // bool
$permissions->hasAny('view', 'edit');    // bool
$permissions->hasAll('view', 'edit');    // bool
```

## Re-connecting is safe

A pair has at most one connection row, and connect() on a pair that already has one only changes what you stage: its status, permissions, expiry and meta are kept unless restated (meta is merged — see Metadata). The config defaults — default\_permissions, default\_status and expiry.default — apply to new connections only. To clear an expiry use extend(null); to change one attribute, use its dedicated verb:

```php
Connections::between($user, $team)
    ->withPermissions('view', 'edit')
    ->expiresIn(now()->addMonth())
    ->connect();

// Re-connecting only changes what you stage: status, permissions and expiry are kept.
Connections::between($user, $team)->withMeta(['note' => 'hi'])->connect();   // merge; perms + expiry kept

// Config defaults (default_permissions, default_status, expiry.default) apply to new
// connections only. To clear an expiry or change one attribute, use its dedicated verb:
Connections::between($user, $team)->extend(null);
Connections::between($user, $team)->permissions()->grant('publish');
Connections::between($user, $team)->accept();
```

After a disconnect() or a prune, connect() — and grant(), permissions()->sync(), invite(), toggle() and sync() — revives the pair as a fresh connection, except a blocked one, which stays blocked (see Invitations & status).

Terminal verbs need a connectable. Running one after from() without to() — or a bulk verb without toMany() — throws MissingConnectable:

```php
Connections::from($user)->connect();       // throws MissingConnectable — call to() first
Connections::from($user)->connectAll();    // throws MissingConnectable — call toMany() first
```

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

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

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/connections-for-laravel.md)
