Basics
A Magewire component combines a PHP class with a .phtml template. Magento layout XML places the component on a page;
Magewire then keeps its public state and the rendered DOM synchronized across update requests.
Before continuing, install and enable Magewire as described on the documentation home page.
Build a counter
The following example creates a complete component, binds it to a Magento block, and calls a PHP action from the browser.
1. Add a component to your Magento module
This example adds a counter to the CMS home page. Start in an existing, enabled
Vendor_Module module. The three files are:
Vendor/Module/
├── Magewire/Counter.php
└── view/frontend/
├── layout/cms_index_index.xml
└── templates/magewire/counter.phtml
<?php
declare(strict_types=1);
namespace Vendor\Module\Magewire;
use Magewirephp\Magewire\Component;
class Counter extends Component
{
public int $count = 0;
public function increment(): void
{
$this->count++;
}
}
The public property is browser-visible state. The public method is an action the browser can call; validate and authorize actions that read or change business data.
2. Render it with PHTML
Magewire makes the component available to its template as $magewire:
<div data-testid="magewire-counter">
<span><?= $escaper->escapeHtml(__('Count: %1', $magewire->count)) ?></span>
<button type="button" wire:click="increment">
<?= $escaper->escapeHtml(__('Increase')) ?>
</button>
</div>
Keep one root element. Magewire uses it to attach the component snapshot and to
update the rendered HTML. Escape text and attributes using Magento's $escaper.
3. Place it with layout XML
The cms_index_index handle places the counter on the CMS home page:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block name="vendor.module.counter"
template="Vendor_Module::magewire/counter.phtml">
<arguments>
<argument name="magewire" xsi:type="object" shared="false">
Vendor\Module\Magewire\Counter
</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
The magewire argument binds the PHP class to this block. shared="false" gives
the block its own component instance, which also makes the pattern safe when you
place the same class more than once on a page.
4. Try it
Open the home page and click Increase. Magewire calls increment() on the
server and updates the count without a full page reload. If the block does not
appear, confirm the module is enabled and that this page uses cms_index_index.
The request cycle
The counter demonstrates Magewire's normal request cycle:
- Magento renders the layout block and component template.
- Magewire serializes the component's public state into a signed snapshot.
wire:click="increment"sends that snapshot and the requested action to the Magewire update route.- Magewire reconstructs the component, calls
increment(), and renders the template again. - The browser processes the response and morphs only the changed DOM.
Component snapshots are browser-visible data. Never put secrets in public properties, and always authorize sensitive actions on the server.
Passing initial values from layout XML
Use a magewire:mount: argument for a named mount() parameter, then assign that value to public state:
<argument name="magewire:mount:label" xsi:type="string">Items</argument>
<argument name="magewire:mount:start" xsi:type="number">19</argument>
public string $label = 'Counter';
public function mount(string $label = 'Counter', int $start = 0): void
{
$this->label = $label;
$this->count = $start;
}
The layout resolver converts kebab-case argument names to camelCase. For example,
magewire:mount:page-size is passed as $pageSize. Although the current resolver parses
magewire.* keys, Magewire 3.7 does not assign those values to public properties.
See Components for every supported binding shape and argument group. Continue with Properties, Actions, and the HTML directives when you are ready to add real behavior.