Examples menu

๐Ÿ—๏ธ Composition API

Class-based page and component API using PHP attributes: #[Signal], #[Signal(Scope::SESSION)], #[Signal(Scope::GLOBAL)], #[Persist], and #[Action].

#[Signal] creates a TAB-scoped reactive signal backed by a client-visible store entry. Client-writable via data-bind. Each browser tab has its own isolated copy.
#[Persist] is a plain server-side instance property โ€” not a signal, not visible to the client. Because the class instance lives for the lifetime of the tab connection, it persists across action calls.
#[Signal(Scope::SESSION)] is a SESSION-scoped signal. Shared across all open tabs of the same browser session. Saving a name here auto-broadcasts to all other tabs instantly.
#[Signal(Scope::GLOBAL)] is a GLOBAL-scoped signal. Shared across every connected user. The totalClicks counter increments for all users simultaneously, regardless of which tab triggered it.
#[Action] marks a public method as a client-callable action. The optional name: argument overrides the URL slug โ€” resetTab is exposed as /_action/reset-tab.
Components + GLOBAL signals โ€” VoteWidget is mounted three times with #[Signal(Scope::GLOBAL)] votes. SignalFactory prefixes the component namespace to scoped signal IDs, giving each animal its own persistent global counter: global_cats_votes, global_dogs_votes, global_parrots_votes.

Session Name Signal(SESSION)

Hello, Anonymous!

Open another tab โ€” saving here updates the greeting in both tabs instantly.

Counter Persist

Count: 0

Each click adds +1, +2, +3โ€ฆ The multiplier is a server-only #[Persist] property โ€” it survives between action calls but is never sent to the client.

Global Clicks Signal(GLOBAL)

Total clicks (all users): 0

Every action on this page increments this counter. Open two browser sessions โ€” clicking in either updates the counter in both.

Vote Widgets Component ร— 3

Same VoteWidget class mounted three times. Signals auto-namespace: cats.votes, dogs.votes, parrots.votes. Clicking one widget never affects the others.

0

0

0

โšก Signals

nameInput string TAB ''

Client-writable input bound via data-bind. Holds the typed name until saveName is called.

name string SESSION Anonymous

Promoted from nameInput by saveName. SESSION scope auto-broadcasts to all tabs of this session.

count int TAB 0

Per-tab counter. Each click adds the current multiplier โ€” grows +1, +2, +3โ€ฆ proving #[Persist] survives between actions.

multiplier int Persist 1

Server-only instance property (not a signal). Invisible to the client. Grows by 1 on each increment call.

totalClicks int GLOBAL 0

Counts every action call by every user. GLOBAL scope auto-broadcasts to all connected sessions.

votes (VoteWidget) int GLOBAL 0

Per-animal vote counter. SignalFactory namespaces the ID: global_cats_votes, global_dogs_votes, global_parrots_votes. Persistent and shared across all users.

๐ŸŽฏ Actions

increment

Adds multiplier to count, then bumps both multiplier and totalClicks.

reset-tab

Resets count and multiplier for this tab only. Custom slug via #[Action(name: 'reset-tab')].

saveName

Copies nameInput โ†’ name (SESSION signal). Auto-broadcasts to all of this user's tabs.

vote

VoteWidget action. Independent per instance: cats.vote, dogs.vote, parrots.vote. Votes persist globally across all users.

๐Ÿ‘ Views

composition.html.twig

Page shell. Renders all signals and three embedded VoteWidget components.

composition_vote.html.twig

VoteWidget component template. Uses the auto-namespaced votes signal and vote action.