Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rialto Laravel Package

nesk/rialto

Rialto is a PHP package that builds a bidirectional bridge between PHP and Node.js, letting PHP call Node.js functions and exchange data through a simple synchronous API. It powers PuPHPeteer and works with custom Node.js processes.

View on GitHub
Deep Wiki
Context7

Getting Started

Three steps to a working bridge:

  1. Install — composer require nesk/rialto (and make sure a Node.js runtime is on the machine/PATH; Rialto shells out to node).
  2. Look at a real implementation first — the package ships no high-level API, only the plumbing. The canonical references are nesk/php-chrome-remote-interface and nesk/php-webdriver by the same author. Read one of those before writing your own process class; the abstraction makes far more sense when you see a full example.
  3. Build your own process class — extend Nesk\Rialto\AbstractProcess, point it at a JS entry script, and declare an Instructions class that maps each PHP method to a snippet of JavaScript.

A minimal process class looks roughly like:

class MyProcess extends AbstractProcess
{
    protected function getDefaultOptions(): array
    {
        return ['nodeExecutable' => 'node'];
    }

    protected function getInstructionsClass(): string
    {
        return MyInstructions::class;
    }

    protected function getScriptPath(): string
    {
        return __DIR__ . '/../resources/bridge.js';
    }
}

Then, from your application code, $process->createResource() opens a handle to a Node-side object, and calling methods on that resource invokes the matching instruction. The very first use case to validate is a trivial one: run a Node script that returns a string, call it from PHP, and echo the result. If that round-trip works, the rest of the abstraction is just ergonomics.

Implementation Patterns

Instruction-driven API surface. Every method you want to call from PHP needs a corresponding instruction. Instructions are declared with a name, an argument list, and a JavaScript handler. The handler receives the resource's underlying Node object plus the serialized arguments. This means your PHP-facing API is fully described up front rather than reflected dynamically — good for reliability, slightly verbose.

Resource handles, not values. Resources returned from Node are wrappers (AbstractResource subclasses), not plain data. That lets you chain calls: $page->navigate($url)->waitForSelector('h1')->textContent(). Model your domain objects as subclasses of AbstractResource and each chained call becomes one instruction. Return scalars and arrays directly where possible to avoid leaking handles into business logic.

Async via promises. Node calls that are asynchronous can return a promise, which PHP resolves through the process loop. This is what makes the package usable for headless-browser automation (page loads, network requests). Use the promise resolution in a loop and be aware that blocking waits block the PHP process — design your call graph so long asynchronous work is started eagerly and awaited once.

Instructions as the seam. Put every Node interaction behind an instruction; never file_get_contents a Node script ad-hoc. This keeps the JS surface versionable and testable independently. It also means you can stub instruction results in PHP tests without spawning Node.

Lifecycle management. Processes have explicit start/stop. Wrap them in a try/finally or a service container binding with a shutdown hook so a crashed PHP request doesn't leave orphaned node processes. For long-lived workers, reuse one process across many resources rather than spawning per request.

Integration with framework code. In Laravel, register the process as a singleton and inject it. Because the process owns the node child, you want it created once per request/job and closed when done. For queue workers, keep it alive across jobs if the Node side is stateless; recreate if the JS module accumulates state.

Gotchas and Tips

  • Archived project. Rialto is no longer maintained. Node.js's module system and protocol surface have moved on since; if you're on modern Node (ESM-first, newer worker_threads semantics), expect friction. Pin Node to an older LTS (14/16 era) or be prepared to patch the bridge script yourself. Weigh this heavily before adopting for new work.
  • Serialization is JSON only. Whatever you send across the boundary is JSON-encoded. DateTime, closures, resources, and cyclic structures will not survive. Convert to scalars before calling into the bridge, and convert back on the PHP side.
  • Errors cross the boundary as exceptions. A thrown JS error surfaces as a PHP exception with the message preserved but the JS stack trace often truncated. For debugging, log the raw instruction/response lines on both sides — that's usually faster than reading the PHP stack.
  • Hanging processes. If a Node instruction never calls back, PHP blocks indefinitely. There is no built-in timeout on the instruction level. Wrap long-running calls with pcntl_alarm (CLI only, not under FPM) or a supervising loop that kills the process.
  • setPathToNode matters on CI. The default node lookup fails in environments where Node is installed at a nonstandard path or under nvm. Set the executable path explicitly via process options; same for the bridge script path, which is resolved relative to the package otherwise.
  • Debug mode. Enabling debug/verbose output on the process (check the AbstractProcess options for the debug flag in your version) prints each message sent and received. This is the single most useful troubleshooting tool when an instruction silently returns null.
  • Extension point: custom instructions. Rather than editing the bundled bridge script, subclass the Instructions class and add methods. Composition of instruction sets lets you layer domain-specific helpers on top of a generic bridge without forking.
  • Two-way calls. The bridge supports Node calling back into PHP methods you've registered. Keep these handlers fast and side-effect-light; a slow PHP handler stalls the whole Node event loop and therefore every pending promise you're waiting on.
  • Test without Node where possible. Because instructions are the seam, most of your PHP logic can be tested against a fake process that returns canned instruction results. Reserve real-Node tests for the integration boundary.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings