Skip to content

Magewire in Hyvä Checkout

Magewire is a port of the popular Laravel Livewire library to Magento. It lets you interact with PHP class properties and methods directly from the browser, with no custom JavaScript or PHP glue code needed. Magewire powers the interactive components in Hyvä Checkout.

This section teaches you just enough about Magewire to get started building and customizing Hyvä Checkout components. Which Magewire version you work with depends on your Hyvä Checkout release line, so start with the version overview below.

Magewire is installed as a dependency of Hyvä Checkout

You don't need to install Magewire separately. Composer pulls it in automatically when you install Hyvä Checkout.

See the Hyvä Checkout installation instructions for details.

Which Magewire Version Hyvä Checkout Uses

Each Hyvä Checkout release line runs on its own Magewire major version:

Hyvä Checkout release line Magewire version Livewire equivalent
Checkout 3.x (3.0.0 and later, plus the 3.0.0 and 1.4.0 betas) Magewire 3 (magewirephp/magewire ~3.7.2) Livewire 3
Checkout 1.x (1.3.x and older, plus the 1.3.1000 betas) Magewire 1 (magewirephp/magewire ^1.13.3) Livewire 2

See Hyvä Checkout Release Lines to find out which line your project uses.

How the Magewire Intro pages are organized

The pages in this section document Magewire 1 behavior in detail, because that is what most existing checkout integrations are written against. Wherever Magewire 3 behaves differently, the page shows the difference in a "Checkout 3.x (Magewire 3)" tab, usually with a link to the matching page of the official Magewire 3 documentation. For everything else about Magewire 3, use the Magewire 3 documentation.

Magewire 1 Code on Checkout 3.x (the v1bc Module)

The v1bc module, which Checkout 3.x installs, keeps components, templates and JavaScript written for Magewire 1 working on Checkout 3.x checkout pages. See The Magewire 1 Backward Compatibility Module (v1bc) for what it covers, and Migrating Checkout Components From Magewire 1 to Magewire 3 for what a module supporting both release lines has to change.

Declaring a Magewire Component in Magento Layout XML

Any Magento block can become a Magewire component by adding a block argument named magewire in layout XML. If you've worked with Magento PHP ViewModels before, this pattern will feel familiar. It's the same approach for injecting an object instance into a block.

The following layout XML example turns a block into a Magewire component by declaring the magewire argument with a PHP class reference:

<!-- Declaring a Magewire component in Magento layout XML -->
<block name="checkout.shipping-details" template="Hyva_Checkout::checkout/address-view/entity-details.phtml">
    <arguments>
        <!-- The argument name "magewire" is the key that activates the Magewire library -->
        <argument name="magewire" xsi:type="object">
            \Hyva\Checkout\Magewire\Checkout\AddressView\ShippingDetails
        </argument>
    </arguments>
</block>

The special argument name magewire is what tells the Magewire library to treat this block's view model as a Magewire component. This magewire view model is the PHP class that the front end can interact with. The magewire argument works the same way on both release lines. Magewire 3 also reads magewire:mount:<name> block arguments and passes them to the component's mount() method as named arguments.

To render values in the HTML page, the .phtml template calls view model methods as usual. The difference is that Magewire adds a special binding syntax that lets the browser call methods on the PHP view model via Ajax. Those method calls can update the view model's properties, and Magewire re-renders the template to update the page automatically.

How Magewire Works Under the Hood

When Magento renders a block that has a magewire view model, the Magewire library adds a few extra HTML attributes to the block's output. The front-end Magewire JavaScript library uses these attributes to initialize a JavaScript object for each Magewire component on the page.

When a visitor interacts with a Magewire component (clicking a button, filling in a field), the JavaScript object sends an Ajax request back to the server. The server invokes the specified view model methods and properties, re-renders the block's template, and sends the updated HTML back to the browser.

Magewire Request Lifecycle and Hooks

During this process, Magewire calls lifecycle hook methods on components (if they are defined). Magewire also provides ways to send messages between components and other useful utilities.

The Magewire library distinguishes between two types of requests:

  • Preceding request: the initial HTTP request during which a Magewire component is rendered for the first time.
  • Subsequent request: any follow-up request triggered by Magewire after a visitor interacts with a component on the page.

Both Magewire versions use these terms.

Magewire 1 to Magewire 3 Cheat Sheet

The table below lists the Magewire differences you are most likely to hit in checkout code. Components in v1 mode on Checkout 3.x get the Magewire 1 behavior through Magewire's own compatibility layer and the v1bc module, so the 3.x column applies to components in v3 mode. Inside the checkout, those are the components that opt out of v1 mode with #[HandleBackwardsCompatibility(enabled: false)].

Topic Checkout 1.x (Magewire 1) Checkout 3.x (Magewire 3)
Sending events from PHP $this->emit('name', ['key' => $value]), $this->emitTo('block.name', ...) $this->dispatch('name', key: $value), chained with ->to('block.name') or ->self()
Listening to events protected $listeners = ['name' => 'method'] #[On('name')] on the method ($listeners still works)
Listener arguments One associative array Named arguments, bound by payload key
Events from templates and JS $emit(), $emitTo(), Magewire.emit(), Magewire.emitTo() $dispatch(), $dispatchTo(), Magewire.dispatch(), Magewire.dispatchTo()
Magewire.on() callback Positional arguments One object: ({ method }) => ...
Magento observer events Every emit also dispatches magewire_<event> Magewire 3 only dispatches a fixed set of magewire_on_* lifecycle events. While the v1bc module is enabled, it dispatches magewire_<event> for every component
wire:model Syncs on every change Deferred until the next request. Use wire:model.live to sync on change
wire:model modifiers .defer, .lazy, .debounce.500ms Plain wire:model, .blur (.lazy is an alias of .change), .live.debounce.500ms
$wire.entangle('foo') Live Deferred. Use $wire.entangle('foo').live
$wire.foo = value Sends a request Updates the browser state only. Use $wire.$set('foo', value) to send it
updating() and updated() arguments ($value, $name) ($name, $value)
Return value of updating*(), updated*() Assigned to the property Ignored. Assign $this->foo yourself
boot() on subsequent requests Runs before the browser state is applied Runs after the browser state is restored, so public properties set in boot() overwrite browser input
boot() and mount() arguments ($blockData, $request) boot() takes none. mount() gets magewire:mount:* layout arguments by name
JavaScript lifecycle events magewire:available, magewire:load magewire:init, magewire:initialized
JavaScript hooks component.initialized, element.initialized, element.updating, element.updated, element.removed, message.sent, message.received, message.processed, message.failed component.init, element.init, morph.updating, morph.updated, morphed, commit (with succeed, fail and respond). Callbacks receive one object
Promise of a $wire method call Resolves without a value Resolves to the PHP method's return value
Magic getFoo() and hasFoo() Available Not available. Read the property directly

Code That Runs on Both Release Lines

An extension that supports Checkout 1.x and 3.x can keep its Magewire 1 code, because the v1bc module runs it on Checkout 3.x checkout pages. When you write new code for both lines, these forms behave the same on Magewire 1, on native Magewire 3 and in v1 mode:

Task Use
Bind a field wire:model.live to sync on change, wire:model.defer to send the value with the next request. A plain wire:model is live on Magewire 1 and deferred on Magewire 3
Change a value in a hook Assign it in updatedFoo($value) and return it. Don't use the generic updated() and updating() hooks, whose arguments are swapped
Send an event between components emit('name', ['key' => $value]) with one associative array, and $listeners. See Events Between PHP Components
Get data back to JavaScript Read a public property after the call. Only Magewire 3 resolves a $wire method call to the PHP return value
Read a property $magewire->foo. Native Magewire 3 components have no magic getFoo()

JavaScript differs more between the two versions. See JavaScript: Lifecycle Events and Hooks.