Laravel Chorus is an event-sourcing based sync-engine designed to sync subsets of your database to your users' on device browser storage, to enable a low-latency web application.
pixelsprout/laravel-chorus is a Laravel package for laravel chorus is an event-sourcing based sync-engine designed to sync subsets of your database to your users' on device browser storage, to enable a low-latency web application..
It currently has 0 GitHub stars and 41 downloads on Packagist.
Install it with composer require pixelsprout/laravel-chorus.
Discover more Laravel packages by pixelsprout
or browse all Laravel packages to compare alternatives.
Last updated
A Laravel-first sync engine designed to seamlessly sync subsets of your database to your users' devices, enabling low-latency web applications.
You can install the package via composer:
composer require pixelsprout/laravel-chorus
Then run the installer to set up Chorus and Laravel Reverb:
php artisan chorus:install
The installer will:
resources/js/chorusFinally, run the migrations:
php artisan migrate
use Pixelsprout\LaravelChorus\Traits\Harmonics;
class User extends Model
{
use Harmonics;
// Specify which fields should be synced using a property
// By default, no fields will be synced unless explicitly defined
protected $syncFields = [
'name',
'email',
];
// Alternatively, you can define a method
public function syncFields(): array
{
return [
'name',
'email',
];
}
// Or override the getSyncFields method for more complex logic
public function getSyncFields(): array
{
// You can include dynamic logic here
$fields = ['name', 'email'];
if ($this->is_admin) {
$fields[] = 'role';
}
return $fields;
}
// Define a filter to limit which records get synced to the client
public function syncFilter()
{
// Only sync records owned by the current user
return $this->where('user_id', auth()->id());
}
}
php artisan chorus:start --reverb
This will start both Chorus and the Laravel Reverb WebSocket server. Changes to models using the Harmonics trait will be automatically broadcast to connected clients.
If you don't want to run Reverb from Chorus, you can run:
php artisan chorus:start
And then start Reverb separately with:
php artisan reverb:start
Chorus comes with built-in TypeScript utilities for integrating with IndexedDB and listening for changes. When you run chorus:install, these utilities are published to your resources/js/chorus directory.
First, set up the database:
// stores/types.ts
import { ChorusDatabase, createChorusDb } from '@/chorus';
interface User {
id: number;
name: string;
email: string;
created_at: Date;
}
const types = createChorusDb('ChorusDatabase') as ChorusDatabase & {
users: Dexie.Table<
User,
'id' // primary key
>;
};
types.initializeSchema({
users: '++id,name,email,created_at',
});
export { types };
Then use the hook in your components:
// pages/dashboard.tsx
import { types } from '@/stores/types';
import { useHarmonics } from '@/chorus/use-harmonics';
interface User {
id: number;
name: string;
email: string;
}
export default function Dashboard() {
const { data: users, isLoading, error, lastUpdate } = useHarmonics<User>('users', types);
return (
<div>
{isLoading ? (
<p>Loading users...</p>
) : error ? (
<p>Error: {error}</p>
) : (
<>
{lastUpdate && <div>Last synchronized: {lastUpdate.toLocaleTimeString()}</div>}
<ul>
{users?.map((user) => (
<li key={user.id}>
<strong>ID: {user.id}</strong> - {user.name} - {user.email}
</li>
))}
</ul>
</>
)}
</div>
);
}
The useHarmonics hook:
You can also use Laravel Echo directly for more control:
import Echo from 'laravel-echo';
import Reverb from '@laravel/reverb-js';
window.Echo = new Echo({
broadcaster: 'reverb',
client: new Reverb('ws://localhost:8080/reverb'),
});
// Listen for changes to a specific table
Echo.channel('chorus.table.users')
.listen('.harmonic.created', (e) => {
console.log('User changed:', e);
});
// Listen for changes to a specific record
Echo.channel('chorus.record.users.1')
.listen('.harmonic.created', (e) => {
console.log('User 1 changed:', e);
});
// Listen for changes relevant to the current user
Echo.private('chorus.user.' + userId)
.listen('.harmonic.created', (e) => {
console.log('User-specific change:', e);
});
You can publish the configuration file with:
php artisan vendor:publish --tag=chorus-config
This will create a config/chorus.php file where you can customize settings.
Harmonics trait is created, updated, or deleted, an event is fired.You can control which records get synced to clients using the syncFilter method:
class Message extends Model
{
use Harmonics;
protected $syncFields = ['content', 'user_id', 'is_read'];
// Only sync messages that belong to the authenticated user
public function syncFilter()
{
return $this->where(function($query) {
$query->where('user_id', auth()->id())
->orWhere('recipient_id', auth()->id());
});
}
}
The syncFilter method should return a query builder instance that filters the records to be synced. This applies to both initial data loading and incremental updates.
For example, if you want to sync only user-specific data, you can filter based on the authenticated user's ID. This ensures that clients only receive data relevant to them, reducing bandwidth usage and improving security.
Contributions are welcome!
The MIT License (MIT).