claviron / laravel
Claviron drivers and adapters for Laravel: cache, sessions, database, broadcasting, queue, schedule, and the Octane client
Requires
- php: ^8.2
- claviron/sapi: 0.1.0
- illuminate/auth: ^11.0 || ^12.0 || ^13.0
- illuminate/broadcasting: ^11.0 || ^12.0 || ^13.0
- illuminate/cache: ^11.0 || ^12.0 || ^13.0
- illuminate/console: ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^11.0 || ^12.0 || ^13.0
- illuminate/log: ^11.0 || ^12.0 || ^13.0
- illuminate/notifications: ^11.0 || ^12.0 || ^13.0
- illuminate/queue: ^11.0 || ^12.0 || ^13.0
- illuminate/session: ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^11.0 || ^12.0 || ^13.0
- monolog/monolog: ^3.0
Requires (Dev)
None
Suggests
- laravel/octane: ^2.0, for Lumenize\Octane\ClavironClient (the application model's request client)
Provides
None
Conflicts
None
Replaces
None
README
The claviron/laravel Composer package exposes Laravel adapters under Lumenize\.
Claviron's native/static classes remain under Claviron\; driver names,
native functions and event topics are unchanged. See the
namespace migration notes before upgrading workers.
Source changes belong in the Lumenize repository.
The standalone Composer repository is generated from committed package sources;
Packagist versions follow its release tags. Composer installs PHP integration
code, not the native Claviron host or the Lumenize executable.
Lumenize owns the package export tooling and release configuration in this
repository; Claviron releases its claviron/sapi dependency independently.
This package replaces Laravel's server-side Pusher HTTP call with Claviron's native broadcast primitive. Browser clients continue to use Laravel Echo and the Pusher WebSocket protocol.
// config/broadcasting.php 'default' => env('BROADCAST_CONNECTION', 'claviron'), 'connections' => [ 'claviron' => [ 'driver' => 'claviron', 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), ], ],
The normal /broadcasting/auth route and routes/channels.php declarations
remain authoritative for private and presence channels. No Pusher PHP SDK or
HTTP publisher is used by this connection.
Fleet-global channel occupancy transitions are ordinary typed Laravel events:
use Lumenize\Broadcasting\Events\ChannelOccupied; use Lumenize\Broadcasting\Events\ChannelVacated; use Illuminate\Support\Facades\Event; Event::listen(ChannelOccupied::class, function (ChannelOccupied $event): void { // $event->appId, $event->channel, $event->time (CarbonImmutable) // Presence channels also carry $event->userId and $event->userInfo. }); Event::listen(ChannelVacated::class, function (ChannelVacated $event): void { // The last fleet subscriber has left this app's channel. });
The package subscribes the persistent application loop to both bus topics.
appId keeps applications separate even when they use the same channel name.
Native SQLite connections
Set 'claviron' => 'example' on a Laravel SQLite connection to use the host's
named example pool. The host must enable sqlite and configure that pool;
missing native support is an error, not a silent PDO fallback. Eloquent,
query events, savepoints and transaction callbacks remain Laravel APIs.
Ordinary Artisan commands continue using Laravel's PDO SQLite driver.
Lumenize console
The lumenize executable runs your application's own Artisan entry. It is
installed separately from the Composer package. From your application directory:
lumenize list
It does not start an HTTP server. If you build the executable from source, its
Rust package is lumenize-cli; see the
CLI guide.
Run that executable from your Laravel application root, for example
/path/to/lumenize list. It executes ./artisan in the native PHP engine;
your autoloader, bootstrap, profiles and custom preparation remain owned by
that local entry. No package runner replaces it, no HTTP server or TaskService
starts, and the entry is not modified. Command arguments, terminal input/output
and the command's exit status are preserved. If ./artisan is missing, the
launcher reports that no Laravel application was found here and exits with
failure. It does not require or automatically install a Composer package.
This entry does not yet attach to a live fleet or prepare native DB/cache
services. Use ordinary PHP drivers for detached commands; explicit Claviron
drivers need a host with those capabilities prepared. --live is not implemented.
The isolated external console check takes a Composer autoloader and the built
binary: php tests/artisan.php /path/to/vendor/autoload.php /path/to/lumenize.
Console configuration
The auto-discovered Lumenize\Providers\LumenizeProvider supplies
defaults only when Laravel is running in console mode. Applications disabling
package discovery register that class in their own provider list.
Without an application config file, config('lumenize.config_path') returns
lumenize.yaml. Optionally publish the defaults:
lumenize vendor:publish --tag=lumenize-config
Override them in your application's config/lumenize.php:
return [ 'config_path' => 'config/example.yaml', ];
The path is relative to the application's working directory. Application values
and cached Laravel configuration remain authoritative. The provider declares
configuration only; it does not yet read that YAML, prepare native services or
attach to Orbit. Ordinary php artisan can also publish this configuration.
Application events
Think in directions relative to this PHP application:
| Direction | Application code | Claviron's role |
|---|---|---|
| Local | Dispatch and listen with Laravel's ordinary event API | Nothing crosses the application boundary unless this class is explicitly relayed or is a FleetEvent. |
| Incoming | Register a FleetEvent class with EventBridge::subscribe(), then use an ordinary Laravel listener |
Claviron receives topic and payload, decodes the registered class, and dispatches it locally. Subscribe before the work whose event matters; there is no replay. |
| Outgoing | Dispatch a FleetEvent or call EventBridge::publish() |
Claviron publishes its stable topic and payload to the application event bus. |
Claviron\Runtime\Event is the incoming native envelope. Laravel code normally
handles the decoded event class, not the envelope or the Orbit link. A link
presence subscriber is optional application behavior; Edge already logs
transport reachability without any PHP subscription.
An ordinary Laravel event can also travel from one PHP worker to another. In
that case, register its class with relay() before Laravel's listener chain
is registered:
use Lumenize\EventBridge; use App\Events\DemoEvent; app(EventBridge::class)->relay([DemoEvent::class]);
Dispatch remains ordinary Laravel code. The bridge converts the event into the
existing Claviron ApplicationEvent: the runtime (php), named application,
Laravel class name, envelope ID, and serialized object travel in one fleet
frame. Rust rejects another runtime or application before PHP sees the frame.
One application worker claims the envelope and runs Laravel's ordinary
listener chain; a ShouldQueue listener therefore enqueues one job for the
application's queue pool. The envelope ID remains transport context and is not
injected into the Laravel event.
Events shared with Rust, JavaScript, or Python use a stable topic and the
FleetEvent contract. relay() is for serialized PHP classes and does not
make that serialization a cross-language contract. Incoming delivery never
publishes the same event back to the bus.
Sessions
The claviron session driver stores Laravel's serialized session payload in a
Claviron cache store. Give sessions their own named cache store so application
cache flushes cannot remove them:
// config/cache.php 'claviron_sessions' => [ 'driver' => 'claviron', 'runtime_store' => 'sessions', 'prefix' => 'my-app-session-', ], // config/session.php 'driver' => env('SESSION_DRIVER', 'claviron'), 'store' => env('SESSION_STORE', 'claviron_sessions'),
The runtime store may compose Orbit L1 with Redis L2. Laravel's session
blocking uses the same cache repository's Orbit lock implementation when
session.block_store selects this store.
An explicit session.store is preserved. If it is absent, null or empty,
the provider uses Laravel's configured cache.default; the driver name
claviron does not require a cache store named claviron.
Bind data to an existing native session
For a route already protected by the host's native auth policy, opt in:
Route::middleware('native.session:api')->group(function () { Route::post('/example', function (Illuminate\Http\Request $request) { $request->session()->flash('notice', 'Saved'); return response()->noContent(); }); });
Register SessionServiceProvider and select session.driver=claviron.
The alias is optional route middleware, not a global API/session boot hook.
The required argument (api above) is a data namespace, not a guard selector;
the host's vhost/route guard must already decide who this request belongs to.
Different namespaces remain separate even for the same native session ID.
StartNativeSession uses the verified native session ID and remaining credential
lifetime, honors session.store or the configured cache default, and emits no
Laravel session cookie. Missing/expired native sessions are rejected. Applications
can subclass allowsGuest() for transient login forms; guest data is never saved.
Subclasses can retain their own native CSRF/audit integration without reimplementing
the identity-to-cache binding. This does not introduce another login or auth session.
Flash retains ordinary Laravel aging and the configured Laravel serialization.
The default PHP-serialized payload is not directly shared with Rust. Laravel's
optional session.serialization=json can provide a readable representation,
but coordinating Rust writes/flash consumption is a separate application concern.