Skip to content

#[AsShortcode]

Register a method as a WordPress shortcode handler.

Signature

php
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class AsShortcode
{
    public function __construct(
        public string $tag,
    ) {}
}

Parameters

ParameterTypeDefaultDescription
tagstringShortcode tag name (required)

Usage

Basic Shortcode

php
<?php

namespace App\Hooks;

use Studiometa\Foehn\Attributes\AsShortcode;

final class Shortcodes
{
    #[AsShortcode('year')]
    public function year(): string
    {
        return date('Y');
    }
}

Usage: [year]2024

With Attributes

php
#[AsShortcode('button')]
public function button(array $atts, ?string $content = null): string
{
    $atts = shortcode_atts([
        'url' => '#',
        'class' => 'btn',
    ], $atts);

    return sprintf(
        '<a href="%s" class="%s">%s</a>',
        esc_url($atts['url']),
        esc_attr($atts['class']),
        esc_html($content ?? 'Click')
    );
}

Usage: [button url="https://example.com"]Learn More[/button]

Enclosing Shortcode

php
#[AsShortcode('spoiler')]
public function spoiler(array $atts, ?string $content = null): string
{
    $atts = shortcode_atts(['title' => 'Spoiler'], $atts);

    return sprintf(
        '<details><summary>%s</summary>%s</details>',
        esc_html($atts['title']),
        do_shortcode($content ?? '')
    );
}

Usage:

[spoiler title="Click to reveal"]
Hidden content here.
[/spoiler]

With Template

php
public function __construct(
    private readonly ViewEngineInterface $view,
) {}

#[AsShortcode('testimonial')]
public function testimonial(array $atts): string
{
    $atts = shortcode_atts(['id' => 0], $atts);

    $post = \Timber\Timber::get_post($atts['id']);
    if (!$post) {
        return '';
    }

    return $this->view->render('shortcodes/testimonial', [
        'testimonial' => $post,
    ]);
}

Security

Always escape shortcode output to prevent XSS vulnerabilities:

php
#[AsShortcode('user_card')]
public function userCard(array $atts): string
{
    $atts = shortcode_atts([
        'name' => '',
        'bio' => '',
        'url' => '#',
    ], $atts);

    return sprintf(
        '<div class="user-card">
            <a href="%s">%s</a>
            <p>%s</p>
        </div>',
        esc_url($atts['url']),       // URLs
        esc_html($atts['name']),     // Plain text
        wp_kses_post($atts['bio'])   // Rich HTML
    );
}

See Security Guide for detailed escaping guidance.

Released under the MIT License.