1. Go to this page and download the library: Download polidog/use-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
polidog / use-php example snippets
// components/Counter.php
use Polidog\UsePhp\Html\H;
use Polidog\UsePhp\Runtime\Element;
use function Polidog\UsePhp\Runtime\fc;
use function Polidog\UsePhp\Runtime\useState;
// Define a counter component with fc() wrapper
$Counter = fc(function(array $props): Element {
[$count, $setCount] = useState($props['initial'] ?? 0);
return H::div(
className: 'counter',
children: [
H::span(children: "Count: {$count}"),
H::button(
onClick: fn() => $setCount($count + 1),
children: '+'
),
H::button(
onClick: fn() => $setCount($count - 1),
children: '-'
),
]
);
}, 'counter'); // 'counter' is the key for state management
// Isolated (default) - State is page-specific
$router->get('/page', PageComponent::class)->isolatedSnapshot();
// Persistent - State is passed via URL when navigating
$router->get('/cart', CartComponent::class)->persistentSnapshot();
// Session - State is stored in session
$router->get('/wizard', WizardComponent::class)->sessionSnapshot();
// Shared - State is shared between specific routes
$router->get('/step1', Step1Component::class)->sharedSnapshot('checkout');
$router->get('/step2', Step2Component::class)->sharedSnapshot('checkout');
// Laravel example
Route::get('/counter', function () {
UsePHP::disableRouter(); // Use NullRouter
return UsePHP::render(Counter::class);
});
// Symfony example
#[Route('/counter')]
public function counter(): Response
{
UsePHP::disableRouter();
return new Response(UsePHP::render(Counter::class));
}
use Polidog\UsePhp\Html\H;
use Polidog\UsePhp\Runtime\Element;
use function Polidog\UsePhp\Runtime\useState;
use function Polidog\UsePhp\Runtime\fc;
// Simple function component (pure, no state)
$Greeting = fn(array $props): Element => H::div(
children: "Hello, {$props['name']}!"
);
// Function component with useState
$Counter = fc(function(array $props): Element {
[$count, $setCount] = useState($props['initial'] ?? 0);
return H::div(children: [
H::span(children: "Count: {$count}"),
H::button(
onClick: fn() => $setCount($count + 1),
children: '+'
),
]);
}, 'counter');
// Function component with snapshot storage (stateless server)
use Polidog\UsePhp\Storage\StorageType;
$SnapshotCounter = fc(function(array $props): Element {
[$count, $setCount] = useState($props['initial'] ?? 0);
return H::div(children: "Count: {$count}");
}, 'snapshot-counter', StorageType::Snapshot);
// Method A: fc() wrapper (Recommended)
// Wrap with fc() for direct invocation with state support
$Counter = fc(function(array $props): Element {
[$count, $setCount] = useState($props['initial'] ?? 0);
return H::div(children: "Count: $count");
}, 'my-counter');
$element = $Counter(['initial' => 5]); // Direct call
$html = UsePHP::renderElement($element);
// Method B: H::component()
// Creates an Element that resolves during render
H::div(children: [
H::component($counterFn, ['initial' => 5, 'key' => 'my-counter']),
]);
// Method C: Direct call (only for pure components without useState)
$Greeting = fn(array $props): Element => H::div(children: "Hello, {$props['name']}!");
$Greeting(['name' => 'World']); // OK - no state needed
use Polidog\UsePhp\Storage\StorageType;
// Session storage (default) - State persists in PHP session
$Counter = fc(fn() => ..., 'key');
$Counter = fc(fn() => ..., 'key', StorageType::Session);
// Memory storage - State resets on each request
$TempForm = fc(fn() => ..., 'key', StorageType::Memory);
// Snapshot storage - State is embedded in HTML (stateless server)
$SnapshotCounter = fc(fn() => ..., 'key', StorageType::Snapshot);
use Polidog\UsePhp\Component\BaseComponent;
use Polidog\UsePhp\Component\Component;
#[Component]
class MyComponent extends BaseComponent
{
public function render(): Element
{
[$count, $setCount] = $this->useState(0);
// ...
}
}
use Polidog\UsePhp\Component\Component;
use Polidog\UsePhp\Storage\StorageType;
// Session storage (default) - State persists across page navigations
#[Component(storage: 'session')]
class TodoList extends BaseComponent { ... }
// Memory storage - State is reset on each page load
#[Component(storage: 'memory')]
class TemporaryForm extends BaseComponent { ... }
// Snapshot storage - State is embedded in HTML, stateless on server
#[Component(storage: 'snapshot')]
class Counter extends BaseComponent { ... }
use function Polidog\UsePhp\Runtime\useState;
// In function components
[$state, $setState] = useState($initialValue);
// Examples
[$count, $setCount] = useState(0);
[$todos, $setTodos] = useState([]);
[$user, $setUser] = useState(['name' => 'John']);
// In class-based components
[$state, $setState] = $this->useState($initialValue);
use Polidog\UsePhp\Psx\CompileCommand;
$app = new UsePHP();
$app->loadComponentManifest(__DIR__ . '/../var/cache/psx/' . CompileCommand::MANIFEST_FILENAME);
// Use a PSX component as a route handler
$router->get('/', function () use ($app) {
\Polidog\UsePhp\Runtime\RenderContext::beginRender();
return $app->renderPsxComponent('App\\Components\\Counter', ['initial' => 0]);
});
namespace App\Pages;
use App\Components\Counter;
use App\Components\Forms\Input as FormInput;
return fn() => (
<div>
<Counter initial={5} />
<FormInput type="email" />
</div>
);
// @psx-runtime App\Legacy\WidgetCounter
#[Component(name: 'UserHeaderDeferred')]
#[Defer(name: 'user-header', cacheControl: 'private, no-store')]
final class UserHeaderDeferred extends BaseComponent
{
public function render(): Element { /* the real content */ }
}
$app->register(UserHeaderDeferred::class); // auto-registers the defer endpoint too
// Class component
#[Defer(name: 'announcement-bar', localCache: true)]
// Closure component in a .psx
fc($render, defer: new Defer(name: 'announcement-bar', localCache: true));
// Class component
#[Defer(name: 'todo-list', reloadable: true)]
// Closure component in a .psx
fc($render, defer: new Defer(name: 'todo-list', reloadable: true));