Laravel Wave

repository·main·Indexed 21 days ago

https://github.com/qruto/laravel-wave

A real-time broadcasting library for Laravel that enables server-sent events (SSE) over native HTTP, eliminating the need for a dedicated WebSocket server. It integrates with Laravel's Redis broadcasting driver and supports Laravel Echo, providing tools for Eloquent model event listening, persistent connection management via sse:ping, and client-side event broadcasting.

Tokens
4.6K
Snippets
19
Records
21
Agent score
74%

What's inside laravel-wave

  1. Install Laravel Wave for Laravel 11 or higher

    main

    For Laravel 11+ projects, install the package via Composer and then run the broadcasting installation command to scaffold the necessary configuration files and Echo setup.

    After installation, the following files are created:

    • routes/channels.php (channel authorization)
    • config/broadcasting.php (broadcasting configuration)
    • resources/echo.js (Echo instance)
    • config/wave.php (optional Wave configuration)
    composer require qruto/laravel-wave
    php artisan install:broadcasting
  2. Install Laravel Wave for Laravel 10 or lower

    main

    For older Laravel versions, you must install the package on both the server (via Composer) and the client (via npm). Additionally, ensure your .env file is configured to use the redis broadcasting driver.

    Required Environment Variable: BROADCAST_DRIVER=redis

    composer require qruto/laravel-wave
    npm install laravel-wave
    BROADCAST_DRIVER = redis
  3. Maintain Persistent Connections with Nginx and PHP-FPM

    main

    Wave automatically reconnects and resumes event history (default 60s) if a connection is lost. However, to maintain a truly persistent connection and avoid timeouts, you must configure your web server.

    Handling fastcgi_read_timeout (Nginx)

    By default, Nginx + PHP FastCGI often has a 60s timeout. You can prevent timeouts by:

    1. Ensuring frequent events: Ensure events are pushed more frequently than the timeout. Wave can send pings automatically based on the ping.frequency config.
    2. Using eager_env: Set ping.eager_env to a specific environment (like local) so pings are sent with every request.
    3. Manual Ping Control: Disable automatic pings (ping.enable => false) and use the sse:ping command to send pings at a specific interval.

    Handling request_terminate_timeout (PHP-FPM)

    Some platforms (like Laravel Forge) terminate requests after 60s. You can disable this in your FPM pool configuration:

    request_terminate_timeout = 0

    Alternatively, configure a separate FPM pool specifically for SSE connections.

    # Send a ping event every 30 seconds manually
    php artisan sse:ping --interval=30
  4. Channel authentication rules in ServerSentEventStream

    main

    The ServerSentEventStream automatically detects if a channel requires authentication based on its name prefix.

    If a channel name starts with either of the following, the stream will attempt to authenticate the request using Laravel's Broadcast::auth() method:

    • private-
    • presence-

    If authentication fails (throwing an AccessDeniedHttpException), the specific event for that channel will be skipped for the current connection.

  5. Configure Server Options for Wave

    main

    To customize the server-side behavior of Wave, publish the configuration file using the Artisan command. The configuration file allows you to control:

    • resume_lifetime: How long (in seconds) an event stream persists to allow resumption after a reconnect. Requires a cache driver.
    • retry: Milliseconds to wait before attempting a reconnect (defaults to null).
    • ping: Configuration for automatic ping events to keep connections alive. Includes enable, frequency (seconds), and eager_env (an array of environments or null).
    • path: The route path used for Wave connections and presence channels (defaults to wave).
    • middleware: Middleware assigned to registered routes (defaults to ['web']).
    • auth_middleware: Middleware used for authenticating presence channels and whisper events (defaults to auth).
    • guard: The authentication guard used (defaults to web).
    php artisan vendor:publish --tag="wave-config"
  6. Install broadcasting dependencies

    main

    Run the broadcasting installation command to set up Laravel Echo, broadcasting routes, and necessary Node dependencies. The command is interactive and will prompt you to:

    1. Enable the Redis broadcasting driver in your .env file.
    2. Install and build Node dependencies (laravel-echo and laravel-wave).
    3. Publish the Wave configuration file.

    If the command fails to install Node dependencies automatically, it will provide the specific commands to run manually based on your package manager (npm, yarn, or pnpm).

    Note: If a routes/channels.php file already exists, the command will error out unless the --force flag is used.

    php artisan broadcasting:install [--force]
  7. Schedule sse:ping in Laravel

    main

    To maintain persistent SSE connections automatically, add the sse:ping command to your Laravel Task Scheduler. This is useful if your server's fastcgi_read_timeout is longer than 60 seconds.

    Example of scheduling the command to run every minute:

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('sse:ping')->everyMinute();
    }
  8. Use Live Eloquent Models with Wave

    main

    Wave provides a Wave class that allows you to listen to Eloquent model events and broadcast notifications using a fluent API. This respects Laravel's native conventions for Model Events Broadcasting and Broadcast Notifications.

    Basic Usage

    Initialize the Wave instance and use the .model() method to target a specific model by its name and primary key.

    Customizing Namespaces

    By default, Wave assumes models are in the App.Models namespace. You can override this during initialization using the namespace option.

    import { Wave } from 'laravel-wave';
    
    // Initialize with custom namespace if needed
    window.Wave = new Wave({namespace: 'App.Path.Models'});
    
    // Listen to events for a specific model instance
    window.Wave.model('User', '1')
        .notification('team.invite', (notification) => {
            console.log(notification);
        })
        .updated((user) => console.log('user updated', user))
        .deleted((user) => console.log('user deleted', user))
        .trashed((user) => console.log('user trashed', user))
        .restored((user) => console.log('user restored', user))
        .updated('Team', (team) => console.log('team updated', team));
  9. Configure Client Options for Wave or Echo

    main

    When initializing a Wave or Echo instance on the client side, you can pass an options object to customize the connection. Key options include:

    • endpoint: The primary SSE connection route (defaults to /wave).
    • namespace: The namespace of events to listen for (defaults to App.Events).
    • auth.headers: An object containing additional authentication headers.
    • authEndpoint: The authentication endpoint (defaults to /broadcasting/auth).
    • csrfToken: The CSRF token (defaults to the XSRF-TOKEN cookie).
    • bearerToken: A bearer token for authentication.
    • request: Custom settings for connection and authentication requests.
    • pauseInactive: If true, the connection closes when the page is hidden and reopens when visible.
    • debug: If true, enables detailed event logs in the console for troubleshooting.
    new Echo({
        broadcaster: WaveConnector,
        endpoint: '/sse-endpoint',
        bearerToken: 'bearer-token',
        //...
    });
    
    // or
    
    new Wave({
        authEndpoint: '/custom-broadcasting/auth',
        csrfToken: 'csrf-token',
    })
  10. Configure Laravel Echo with WaveConnector

    main

    To use Wave with Laravel Echo, import WaveConnector from laravel-wave and pass it as the broadcaster option when initializing the Echo instance.

    import Echo from 'laravel-echo';
    import { WaveConnector } from 'laravel-wave';
    
    window.Echo = new Echo({broadcaster: WaveConnector});
  11. Configure SSE connection heartbeats (Ping)

    main

    The PingConnections middleware maintains active Server-Sent Events (SSE) connections by emitting SsePingEvent heartbeats. This prevents connections from being closed by proxies or load balancers due to inactivity.

    Configuration is managed via the wave.ping config keys:

    • wave.ping.enable (boolean): Enables or disables the ping mechanism. Defaults to true.
    • wave.ping.frequency (integer): The interval in seconds between pings. The ping is sent if the time elapsed since the last event exceeds this value. Defaults to 30.
    • wave.ping.eager_env (string): An environment name (e.g., local) where pings are sent eagerly (every request) regardless of the frequency setting. Defaults to local.
    // Example configuration in config/wave.php
    'ping' => [
        'enable' => true,
        'frequency' => 30,
        'eager_env' => 'local',
    ],
  12. Configure `PHP_CLI_SERVER_WORKERS` for SSE

    main

    To support real-time Server-Sent Events (SSE) broadcasting in a local development environment, you must increase the number of PHP CLI server workers.

    Via CLI Prompt

    When running php artisan serve, if WaveServiceProvider is detected and PHP_CLI_SERVER_WORKERS is set to 1, you will be prompted to select a new worker count (e.g., 10 or 20). You can also choose to save this setting directly to your .env file during the prompt.

    Via Environment Variable

    You can manually set the number of workers in your .env file to ensure the server handles the necessary concurrent connections:

    PHP_CLI_SERVER_WORKERS=10