# corrivate/magento2-layout-bricks

> Use layout bricks in Magento, inspired by Laravel anonymous Blade components

`composer require corrivate/magento2-layout-bricks`

Canonical URL: https://packagento.com/corrivate/magento2-layout-bricks

## At a glance

- **Vendor**: corrivate (https://packagento.com/corrivate.md)
- **Latest version**: 0.1.3 — released 2026-07-01
- **Pricing**: Free
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

Packagento is licence-gated, so even free packages need a licence on a project before Composer can resolve them.

1. **Sign in or create an account** at https://packagento.com/customer/account/.

2. **Add the package to your account.** Open https://packagento.com/corrivate/magento2-layout-bricks and complete the free checkout. A licence is minted automatically.

3. **Create or pick a project, then activate the licence on it.**
   - Projects represent the Magento installs you deploy to. Manage them at https://packagento.com/projects/.
   - Activate the new licence on the project you'll deploy this package to. Activation is what generates the Composer credentials scoped to that project.

4. **Add the project credentials to your Magento codebase.**

   Grab the project's public + private key from https://packagento.com/projects/ (open the project, then its Credentials tab), and add them to `auth.json`:

   ```json
   {
     "http-basic": {
       "packagento.com": {
         "username": "ppk_live_...",
         "password": "psk_live_..."
       }
     }
   }
   ```

   Add the Packagento Composer repository to `composer.json`:

   ```json
   {
     "repositories": [
       { "type": "composer", "url": "https://packagento.com" }
     ]
   }
   ```

5. **Install and apply.**

   ```bash
   composer require corrivate/magento2-layout-bricks:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Use layout bricks in Magento, inspired by Laravel anonymous Blade components

## README

[![Latest Version on Packagist](https://img.shields.io/packagist/v/corrivate/magento2-layout-bricks?color=blue)](https://packagist.org/packages/corrivate/magento2-layout-bricks)
[![MIT Licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md)

*All in all you're just another brick in the layout*

```bash
composer require corrivate/magento2-layout-bricks
```

Modern frontend frameworks embrace reusable components, like buttons, input fields, and cards. And they style them with utility CSS like Tailwind. It's fine to pile a dozen classes on that primary button, because you only have to build it once.

Magento doesn't come with this out of the box. Many templates are *huge* and if you talk about UI components people make the sign of the ~~cross~~ XML at you. 

This package is a way to make things better. To use small anonymous components without hassle. It's heavily inspired by Laravel's anonymous blade components. In Magento, our unit of frontend template is a block. An anonymous block is a **brick**.

### An example phtml template
```php
<?php declare(strict_types=1);
/** @var \Magento\Framework\View\Element\Template $block */
/** @var \Magento\Framework\Escaper $escaper */
/** @var \Corrivate\LayoutBricks\Model\Mason $mason */
?>

<form method="post" action="/newsletter/subscribe">
<?= $mason('cms.block', props: ['block_id' => 'newsletter-explanation']) ?>

<?= $mason('ExampleCorp_ExampleModule::theme/input/text.phtml', [
    'required', 
    'class' => 'rounded-md text-stone-800 bg-stone-100', 
    'placeholder' => 'joe@examplecorp.com'
]) ?>

<?= $mason('btn-primary', attributes: ['type' => 'submit'], props: ['label' => __('Save')]) ?>
</form>
```

### How does it work?

The `$mason` object is globally injected into every `.phtml` template. It has just one method, `__invoke()`, to cause it to output as a string a fully rendered child block. So it's essentially a compact, ergonomic way of doing this:

```php
<?= $block
    ->getLayout()
    ->createBlock(\Magento\Framework\View\Element\Template::class)
    ->setTemplate($template) 
?>
```

This is already nice, because we are now still using Magento's templating engine:
* We can call small templates without using a ton of boilerplate. It's now realistic to make a template for something as small as a single button. So we can re-use the same button look and feel throughout the entire website. This is really helpful if the button actually has a LOT of utility CSS classes. Hi Tailwind.
* We can make a library of base components as a reusable module. 
* We still have the opportunity to use Magento's theme overrides. We can change the way buttons look in a website or single store. But because we're re-using the button template everywhere, we can change it in one place and have the change happen everywhere.

But there's more:

* You can set default HTML attributes (such as classes) on a component, and inject additional ones based on the context. They will be merged, with new properties overriding default ones.
* You can inject props into a component, supplying them with data.

For example, consider the `cms.block` brick: 
```php
<?= $mason('cms.block', 
        attributes: ['class' => 'border-2 border-stone-400 rounded-lg'], 
        props: ['block_id' => 'text-block']) 
?>
```

This will render the CMS block with ID 'text-block', but surround it in a div with a gray round border.

### Aliases

[Aliases in detail](docs/Aliases.md)

You can place bricks in two ways:
* Fully cite the Magento template path:

```php
<?= $mason('Corrivate_LayoutBricks::cms/block.phtml', props: ['block_id' => 'test-block']) ?>
``` 

* Create an **alias** for it, so you can refer to it more shortly: 

```php
<?= $mason('cms.block', props: ['block_id' => 'test-block']) ?>
``` 

[Aliases in detail](docs/Aliases.md)

### Attributes

[Attributes in detail](docs/Attributes.md)

The `$mason` objects invoke method accepts an array of attributes. For example:

```php
<?= $mason('input.text', attributes: [
    'required', 
    'disabled' => false, 
    'class' => 'text-black', 
    'placeholder' => 'your input please', 
    'name' => 'user_comment'
]) ?>
```

In the brick template, this will be available as a BrickAttributesBag which could for example have the following default attributes/values:

```php
<input <?= $attributes->default([
    'class' => 
    'bg-white', 
    'disabled' => true, 
    'type' => 'text'
]) ?> />
```

This would result in the following HTML after the defaults and your custom input is merged:

```html
<input class="bg-white text-black" 
       type="text" 
       required 
       placeholder="your input please" 
       name="user_comment"/>
```

[Attributes in detail](docs/Attributes.md)

### Props

[Props in detail](docs/Props.md)

Props are used to pass data to the brick. For example, if you were making a brick to render a "product card", you'd pass the product that needs to be displayed:

```php
<?= $mason('product-cart', props: ['product' => $product]) ?>
```

In the brick template, the props are available through the `$props` variable, which is automatically present:

```php
<?php declare(strict_types=1);
/** @var \Magento\Framework\View\Element\Template $block */
/** @var \Magento\Framework\Escaper $escaper */
/** @var \Corrivate\LayoutBricks\Model\BrickAttributesBag $attributes */
/** @var \Corrivate\LayoutBricks\Model\BrickPropsBag $props */
?>

<div class="border-2 border-color-stone-600 rounded-md">
    <?= $props['product']->getSku() ?>
</div>

```

The `$props` variable is not an array, but it implements `ArrayAccess` to give access to its contents.

The `$props` variable also has a `$props->default([])` method so you can supply default (scalar) props. You can always override those default from the parent template. 

The `$props` object also has a `$props->expect([])` method which allows you to specify expected props and their data types so you can opt into greater type safety.

[Props in detail](docs/Props.md)

_(README truncated for .md surface. Full README on https://packagento.com/corrivate/magento2-layout-bricks.)_

## Changelog

### 0.1.3
#### Fixed
typo

### 0.1.2
#### Added
- PHP 8.4 and 8.5 support

## Recent Versions

| Version | Released |
|---|---|
| 0.1.3 | 2026-07-01 |
| 0.1.2 | 2026-07-01 |
| v0.1.1 | 2024-09-18 |
| v0.0.3 | 2024-09-15 |
| v0.1.0 | 2024-09-15 |
| v0.0.2 | 2024-09-14 |
| v0.0.1 | 2024-09-12 |

## Dependencies

### Require

| Package | Constraint |
|---|---|
| magento/framework | * |
| magento/module-cms | * |
| php | ~7.4.0\|\|~8.0.0\|\|~8.1.0\|\|~8.2.0\|\|~8.3.0\|\|~8.4.0\|\|~8.5.0 |

### Require (dev)

| Package | Constraint |
|---|---|
| bitexpert/phpstan-magento | ^0.32.0 |
| phpstan/extension-installer | ^1.4 |
| phpstan/phpstan | ^1.12 |

## Quality

Latest release (0.1.3) fails the Packagento QA pipeline. Verdicts below are per-cell (Magento line × PHP version) for the matrixed tools, and run-once for the static / security tiers.


### Compatibility

Each Magento line is installed on its supported PHP versions, then the module is built (DI compile + static-content deploy). Cells show passed / failed / untested; staircase gaps render as `–`.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | Pass | Pass | – | – |
| 2.4.8 | – | Pass | Pass | – |
| 2.4.9 | – | – | Pass | Pass |


### Code Quality

Advisory checks against the module's source. Never affect the Compatibility verdict — a phpcs finding can't make a module incompatible.

#### Static Analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| PHPCS | Fail | 82 | 4 errors, 78 warnings (ruleset: Magento2), 22 auto-fixable with phpcbf |
| PHPMD | Warning | 5 | 5 rule violations (UnusedPrivateField:5) |
| Cpd | Pass | 0 |  |
| Composer validate | Info | 3 | valid; 3 advisory notes (composer validate --strict) |

#### PHPStan

Type-checks the module against a real Magento install. Re-runs per Magento + PHP version because resolvable symbols differ between releases.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | Pass | Pass | – | – |
| 2.4.8 | – | Pass | Pass | – |
| 2.4.9 | – | – | Pass | Pass |


### Tests

Unit and integration suites run per Magento + PHP cell. Test failures speak to the module's behaviour, not its compatibility with a line, so they're reported here separately.

#### Unit Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |

#### Integration Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |


### Security

Dependency-advisory audit (composer audit) plus a source malware scan. A malware detection fails the version outright.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| Composer audit | Pass | 0 |  |
| Malware scan | Pass | 0 |  |

## Licence and pricing

Free. A licence is still minted on checkout and bound to your project for Composer access — no payment step.

Refundable within 14 days of first purchase via https://packagento.com/account/refunds/.

## Install via Claude Code or any MCP client

The Packagento MCP server can run the licence + project + Composer steps above in one tool call:

```
purchase_and_install_packages(
  composer_names=["corrivate/magento2-layout-bricks"],
  project_id="proj_xxx"
)
```

This handles cart, checkout, licence minting, project activation, and writes auth.json credentials. Connect a client with `claude mcp add packagento https://mcp.packagento.com`. Full setup at https://packagento.com/docs/mcp-setup.

## Vendor

corrivate is a Magento 2 vendor on Packagento. See https://packagento.com/corrivate.md for their full catalogue.

