Skip to content

BlockPatternInterface

Optional interface for block patterns with dynamic content.

Signature

php
<?php

namespace Studiometa\Foehn\Contracts;

interface BlockPatternInterface
{
    /**
     * Compose data for the pattern template.
     *
     * May return a plain array or an Arrayable DTO.
     *
     * @return array<string, mixed>|Arrayable Context variables for the template
     */
    public function compose(): array|Arrayable;
}

Methods

compose()

Return data that will be passed to the pattern's Twig template. Can return either a plain array or an Arrayable DTO.

php
public function compose(): array
{
    return [
        'posts' => \Timber\Timber::get_posts([
            'posts_per_page' => 3,
        ]),
        'categories' => \Timber\Timber::get_terms('category'),
    ];
}

Usage

This interface is optional. Simple patterns don't need it:

php
// Static pattern - no interface needed
#[AsBlockPattern(
    name: 'theme/hero',
    title: 'Hero Section',
    categories: ['featured'],
)]
final class HeroPattern {}

For dynamic content, implement the interface:

php
<?php

namespace App\Patterns;

use Studiometa\Foehn\Attributes\AsBlockPattern;
use Studiometa\Foehn\Contracts\BlockPatternInterface;

#[AsBlockPattern(
    name: 'theme/latest-posts',
    title: 'Latest Posts Grid',
    categories: ['posts'],
)]
final class LatestPosts implements BlockPatternInterface
{
    public function compose(): array
    {
        return [
            'posts' => \Timber\Timber::get_posts([
                'post_type' => 'post',
                'posts_per_page' => 3,
            ]),
        ];
    }
}

Template

twig
{% verbatim %}{# patterns/latest-posts.twig #}
<!-- wp:columns -->
<div class="wp-block-columns">
    {% for post in posts %}
    <!-- wp:column -->
    <div class="wp-block-column">
        <!-- wp:heading {"level":3} -->
        <h3>{{ post.title }}</h3>
        <!-- /wp:heading -->

        <!-- wp:paragraph -->
        <p>{{ post.excerpt }}</p>
        <!-- /wp:paragraph -->
    </div>
    <!-- /wp:column -->
    {% endfor %}
</div>
<!-- /wp:columns -->{% endverbatim %}

With Arrayable DTO

php
use Studiometa\Foehn\Contracts\Arrayable;
use Studiometa\Foehn\Concerns\HasToArray;

final readonly class FeaturedContext implements Arrayable
{
    use HasToArray;

    public function __construct(
        public array $products,
        public string $heading,
    ) {}
}

#[AsBlockPattern(name: 'theme/featured-products', title: 'Featured Products')]
final class FeaturedProducts implements BlockPatternInterface
{
    public function __construct(
        private readonly ProductService $products,
    ) {}

    public function compose(): FeaturedContext
    {
        return new FeaturedContext(
            products: $this->products->getFeatured(4),
            heading: __('Featured', 'theme'),
        );
    }
}

Released under the MIT License.