PHPackages                             splitstack/translucid - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. splitstack/translucid

ActiveLibrary[API Development](/categories/api)

splitstack/translucid
=====================

Realtime model updates for Laravel via Postgres LISTEN/NOTIFY or Eloquent lifecycle events

v0.1.3(1mo ago)0183↓18%MITPHPPHP ^8.2CI failing

Since May 5Pushed 1mo agoCompare

[ Source](https://github.com/EmilienKopp/translucid)[ Packagist](https://packagist.org/packages/splitstack/translucid)[ RSS](/packages/splitstack-translucid/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (4)Versions (3)Used By (0)

Translucid
==========

[](#translucid)

Real-time model change broadcasting for Laravel — powered by PostgreSQL `LISTEN/NOTIFY` or Eloquent lifecycle events.

When a row changes in your database, Translucid fires a Laravel broadcast event on a private channel. Your frontend can subscribe and react instantly, without polling.

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13
- PostgreSQL (required for the DB-mode listener)
- `laravel/pennant` ^1.0

Installation
------------

[](#installation)

```
composer require splitstack/translucid
```

Publish the config:

```
php artisan vendor:publish --tag=translucid-config
```

---

How it works
------------

[](#how-it-works)

Translucid supports two broadcast sources — you pick one (or both) per scope via Pennant feature flags:

ModeHow events are triggered**From DB** (`TranslucidFromDB`)PostgreSQL triggers call `pg_notify`. A long-running `translucid:listen` command picks them up and dispatches broadcast events.**From App** (`TranslucidFromApp`)The `HasTranslucid` trait adds Eloquent observers (`created`, `updated`, `deleted`) that dispatch broadcast events inline.Both modes emit the same three events: `TranslucidCreated`, `TranslucidUpdated`, `TranslucidDeleted`.

---

Getting started
---------------

[](#getting-started)

### 1. Install database triggers (DB mode)

[](#1-install-database-triggers-db-mode)

Create a migration to register PostgreSQL triggers for each model you want to observe:

```
use App\Models\Post;
use Illuminate\Database\Migrations\Migration;
use Splitstack\Translucid\Facades\Translucid;

return new class extends Migration
{
    public function up(): void
    {
        Translucid::observe(Post::class);
    }

    public function down(): void
    {
        Translucid::unobserve(Post::class);
    }
};
```

Run migrations, then start the listener:

```
php artisan translucid:listen
```

### 2. Add the trait (App mode)

[](#2-add-the-trait-app-mode)

Add `HasTranslucid` to any Eloquent model to broadcast changes via Eloquent observers instead:

```
use Splitstack\Translucid\Concerns\HasTranslucid;

class Post extends Model
{
    use HasTranslucid;
}
```

### 3. Activate a feature flag

[](#3-activate-a-feature-flag)

Both modes are gated by Pennant. Activate the flag for the scope you want (a user, tenant, or `null` for global):

```
use Laravel\Pennant\Feature;
use Splitstack\Translucid\Features\TranslucidFromDB;
use Splitstack\Translucid\Features\TranslucidFromApp;

// Activate DB mode globally
Feature::activate(TranslucidFromDB::class);

// Or activate App mode for a specific user
Feature::for($user)->activate(TranslucidFromApp::class);
```

---

Broadcast payload
-----------------

[](#broadcast-payload)

Events broadcast on a **private channel** (default: `translucid`). Each event carries:

```
{
  "type": "posts",
  "model": "App\\Models\\Post",
  "id": "42",
  "op": "updated",
  "changes": { "title": "New title" }
}
```

The broadcast event name includes the table and record key:

```
translucid.updated.posts.42
translucid.created.posts.42
translucid.deleted.posts.42

```

---

Configuration
-------------

[](#configuration)

`config/translucid.php`:

```
return [
    // Base channel name (private channel). Multi-tenant mode appends ".{tenant}".
    'default_channel' => 'translucid',

    // Set a TenantDriver class for per-tenant channel scoping and per-tenant
    // PostgreSQL connections. null = single-tenant.
    'tenant_driver' => null,

    // Attribute on the Tenant model appended to the channel name.
    // Produces channels like "translucid.{tenant.space}".
    'tenant_channel_attribute' => 'space',

    // Laravel DB connection used for per-tenant PDO connections.
    'tenant_connection' => 'tenant',

    // Microseconds to sleep between LISTEN polling loops.
    'listen_sleep' => 50_000,
];
```

---

Multi-tenancy
-------------

[](#multi-tenancy)

### Built-in Spatie driver

[](#built-in-spatie-driver)

If you use `spatie/laravel-multitenancy`, configure the built-in driver:

```
// config/translucid.php
'tenant_driver' => \Splitstack\Translucid\Tenancy\SpatieMultitenancyDriver::class,
'tenant_channel_attribute' => 'space', // attribute on your Tenant model
'tenant_connection' => 'tenant',       // Laravel DB connection for tenant DBs
```

The listener will open a separate PostgreSQL `LISTEN` connection per tenant and broadcast on scoped channels like `translucid.acme`.

### Custom driver

[](#custom-driver)

Implement the `TenantDriver` contract to integrate any tenancy strategy:

```
use PDO;
use Splitstack\Translucid\Contracts\TenantDriver;

class MyTenantDriver implements TenantDriver
{
    // Returns the broadcast channel for the currently active tenant.
    public function resolveChannel(): string
    {
        return 'translucid.' . MyTenancy::current()->slug;
    }

    // Returns a channel => PDO map. Each PDO must already have LISTEN issued.
    public function resolveListenConnections(): array
    {
        $connections = [];
        foreach (Tenant::all() as $tenant) {
            $pdo = new PDO(/* ... */);
            $pdo->exec('LISTEN translucid');
            $connections['translucid.' . $tenant->slug] = $pdo;
        }
        return $connections;
    }

    // Returns the Pennant scope string for the given tenant.
    public function resolveFeatureScope(mixed $scope): ?string
    {
        return 'translucid.' . $scope->slug;
    }
}
```

Register it in `config/translucid.php`:

```
'tenant_driver' => MyTenantDriver::class,
```

### Custom channel resolver (without a driver)

[](#custom-channel-resolver-without-a-driver)

For simple cases you can override the channel resolver directly in a service provider:

```
use Splitstack\Translucid\Translucid;

Translucid::resolveChannelUsing(fn () => 'my-app.' . auth()->id());
```

---

Artisan commands
----------------

[](#artisan-commands)

CommandDescription`php artisan translucid:listen`Start polling PostgreSQL for notifications and dispatching broadcast events. Handles `SIGINT`/`SIGTERM` for graceful shutdown.---

Events reference
----------------

[](#events-reference)

EventBroadcast name`op` value`TranslucidCreated``translucid.created.{table}.{id}``created``TranslucidUpdated``translucid.updated.{table}.{id}``updated``TranslucidDeleted``translucid.deleted.{table}.{id}``deleted`All three are standard Laravel broadcastable events and work with any broadcasting driver (Reverb, Pusher, Ably, etc.).

---

Testing
-------

[](#testing)

```
composer test
```

---

License
-------

[](#license)

MIT — see [LICENSE.md](LICENSE.md).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance93

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

35d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b9e77e55bb8341a1fa99f8348597070b4de230b5fc457e866e4f196dd56843f1?d=identicon)[EmilienKopp](/maintainers/EmilienKopp)

---

Top Contributors

[![EmilienKopp](https://avatars.githubusercontent.com/u/91975560?v=4)](https://github.com/EmilienKopp "EmilienKopp (6 commits)")

---

Tags

laravelpostgresWebSocketsrealtimenotifyBroadcastinglisten

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/splitstack-translucid/health.svg)

```
[![Health](https://phpackages.com/badges/splitstack-translucid/health.svg)](https://phpackages.com/packages/splitstack-translucid)
```

###  Alternatives

[statamic/cms

The Statamic CMS Core Package

4.8k3.5M901](/packages/statamic-cms)[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

2.9k36.4M124](/packages/darkaonline-l5-swagger)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k13.5M59](/packages/knuckleswtf-scribe)[mozex/anthropic-laravel

Laravel integration for the Anthropic API: facade, config publishing, install command, testing fakes, messages, streaming, tool use, thinking, and batches.

74287.1k1](/packages/mozex-anthropic-laravel)[coreproc/nova-echo

Adds Laravel Echo with your broadcast configuration to your Laravel Nova app

1997.8k2](/packages/coreproc-nova-echo)[yakovenko/laravel-lighthouse-graphql-multi-schema

A Laravel package that provides multi-schema support for Lighthouse GraphQL.

17112.5k](/packages/yakovenko-laravel-lighthouse-graphql-multi-schema)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
