Live binding
Name your spacecraft and see its call sign update.
Call sign: awaiting a name.
<label for="demo-name">Spacecraft name</label>
<input id="demo-name" name="name"
x-interact:model.live> Meet CakePHP Interact
Build interactive CakePHP interfaces with PHP and Alpine. Add live search, responsive forms, and smooth page visits without leaving the stack you know.
For CakePHP 6.x · PHP 8.5+CakePHP 6 is currently unreleased.
PHP state & actions Alpine, included
<?php
class ExoplanetsIsland extends Island
{
#[State(writable: true)]
public string $search = '';
#[Pagination(url: true, history: ['page'])]
public PaginationState $paging;
public function viewData(): array
{
$planets = $this->fetchTable(ExoplanetsTable::class);
$query = $planets->find('search', search: $this->search);
return ['planets' => $this->paginate($query, ['limit' => 2])];
}
} <?php
/** @var \App\Model\Entity\Exoplanet $planet */
?>
<form x-interact:submit="$server.sync()">
<label for="planet-search">Find a planet</label>
<input id="planet-search" type="search" name="search"
x-interact:model.live>
</form>
<?php foreach ($planets as $planet): ?>
<p><?= h($planet->name) ?></p>
<?php endforeach; ?>
<?= $this->Paginator->prev('Previous') ?>
<?= $this->Paginator->next('Next') ?> 300 planets in the collection
PHP → HTMLDiscovered in 2004
Discovered in 2004
Planet data from the NASA Exoplanet Archive.
Try Interact
Try each interaction, then take a peek at the code that makes it work.
Name your spacecraft and see its call sign update.
Call sign: awaiting a name.
<label for="demo-name">Spacecraft name</label>
<input id="demo-name" name="name"
x-interact:model.live> Pack supplies with an action that runs in PHP.
<?php
#[Action]
public function increment(): void
{
$this->count++;
} Run a simulated system check and see when it is working.
Simulated check · 450ms
<button :disabled="$server.busy">
<span x-show="$server.busy">Working…</span>
</button> Choose your display spacing. The URL remembers it.
<?php
#[State(writable: true, url: true, history: true)]
public string $density = 'comfortable'; Keep the mission clock fresh while this island is visible.
Mission clock · UTC · Updates every 5 seconds
<section x-interact:poll.5s.visible>
<!-- Fresh PHP output, just here. -->
</section> Open mission details instantly with local browser state.
Destination: the stars. This detail opens locally.
<div x-data="{ expanded: false }">
<button @click="expanded = !expanded">
View mission details
</button>
</div> Send a signal from one island and watch another respond.
<?php
// In the sending island:
#[Action]
public function send(): void
{
$this->dispatch('mission-signal');
}
// In the receiving island:
#[Action(on: 'mission-signal')]
public function receive(): void
{
$this->received++;
} Watch a simulated mission report arrive in stages from one PHP action.
Simulated report · One request, three updates.
<?php
#[Action(stream: true)]
public function generate(): void
{
$line = 'Scanning the horizon.';
$this->stream('report', $line . "\n");
} More with Interact
There is more to explore when your application needs it.
Refresh subscribed islands or receive events from other requests and jobs. Bring a provider adapter, including the optional Mercure integration.
Realtime subscriptionsUse real links with enhanced navigation. Titles, history, scroll, and focus follow the visit without a full browser reload.
Explore navigationPass your ORM query to paginate(). The Paginator helper produces real links that update the island and keep its filters in the URL.
Paginate an islandNest independent islands, pass reactive props, bind child values, and coordinate through events. Load them lazily when useful.
Compose islands Explore lazy loadingSend files with your island action and show upload progress. Keep validation, storage, and permissions in your CakePHP application.
Handle uploadsSee how it works
The search above uses a local snapshot from the NASA Exoplanet Archive. Filters stay in the URL, and PHP runs a CakePHP finder to return fresh HTML.
<?php
class ExoplanetsIsland extends Island
{
#[State(writable: true)]
public string $search = '';
#[Pagination(url: true, history: ['page'])]
public PaginationState $paging;
public function viewData(): array
{
$planets = $this->fetchTable(ExoplanetsTable::class);
$query = $planets->find('search', search: $this->search);
return ['planets' => $this->paginate($query, ['limit' => 2])];
}
} <?php
/** @var \App\Model\Entity\Exoplanet $planet */
?>
<form x-interact:submit="$server.sync()">
<label for="planet-search">Find a planet</label>
<input id="planet-search" type="search" name="search"
x-interact:model.live>
</form>
<?php foreach ($planets as $planet): ?>
<p><?= h($planet->name) ?></p>
<?php endforeach; ?>
<?= $this->Paginator->prev('Previous') ?>
<?= $this->Paginator->next('Next') ?> A search box, a live preview, or an inline editor. Add Interact where your application needs it.
Requires PHP 8.5+ and CakePHP 6.x, currently unreleased.