پترن سفارشی در وردپرس یک الگوی از پیش آماده از بلاک‌های گوتنبرگ است که با کد PHP یا JavaScript ثبت می‌شود و به کاربران اجازه می‌دهد ساختارهای پیچیده محتوایی را با یک کلیک درج کنند. پترن‌ها از وردپرس ۵.۵ به‌عنوان یک ویژگی رسمی معرفی شدند و در نسخه‌های بعدی با قابلیت‌هایی مثل Synced Patterns (پترن‌های همگام‌شده)، Pattern Overrides و Pattern Categories تکامل یافتند. ثبت پترن با کد، کنترل کامل بر ساختار، دسترس‌پذیری و بین‌المللی‌سازی را در اختیار توسعه‌دهنده قرار می‌دهد و از وابستگی به رابط کاربری Site Editor جلوگیری می‌کند. این مقاله چارچوب فنی کامل ثبت پترن با PHP و JavaScript، مدیریت دسته‌بندی‌ها، Overrideها، و یکپارچگی با قالب‌های بلاکی را ارائه می‌دهد.

اولین باری که یک پترن سفارشی برای یک آژانس طراحی ساختم، هدف ساده بود: کاهش زمان تولید صفحات فرود. اما نتیجه فراتر رفت: تیم محتوا از ۴۵ دقیقه به ۵ دقیقه رسید و خطاهای طراحی به صفر کاهش یافت. آن تجربه نشان داد که پترن‌ها نه فقط یک ابزار راحتی، بلکه یک ابزار انضباط طراحی هستند که کیفیت را در مقیاس تضمین می‌کنند.

پترن وردپرس چیست و چه تفاوتی با بلاک قابل بازاستفاده دارد؟

پترن (Pattern) در وردپرس یک ترکیب از پیش تعریف‌شده از بلاک‌های گوتنبرگ است که کاربر می‌تواند آن را در ویرایشگر درج کند و سپس محتوای آن را ویرایش نماید. پترن‌ها از وردپرس ۵.۵ به‌عنوان یک ویژگی رسمی معرفی شدند، اما مفهوم آن‌ها از Reusable Blocks (بلاک‌های قابل بازاستفاده) در نسخه‌های قبلی گوتنبرگ نشأت می‌گیرد. اگر با گوتنبرگ و تحول ویرایش محتوا در وردپرس آشنا شده باشید، این تکامل را به‌عنوان یک مسیر منطقی می‌شناسید.

تفاوت اصلی بین پترن و بلاک قابل بازاستفاده در مدل همگام‌سازی است. بلاک قابل بازاستفاده (که امروز Synced Pattern نامیده می‌شود) یک نمونه واحد است که در چندین صفحه استفاده می‌شود و تغییر آن، تمام نمونه‌ها را به‌روزرسانی می‌کند. پترن (که امروز Unsynced Pattern نامیده می‌شود) یک الگوی اولیه است که با درج، به یک کپی مستقل تبدیل می‌شود و تغییر آن، فقط همان نمونه را تحت تأثیر قرار می‌دهد.

«پترن یک قالب است، نه یک نسخه. شما ساختار را یک‌بار تعریف می‌کنید و سپس هر کاربر، نسخه خودش را می‌سازد.»

سه سطح تفاوت بین پترن و بلاک قابل بازاستفاده:

معیار Unsynced Pattern Synced Pattern
همگام‌سازی مستقل پس از درج همگام در تمام نمونه‌ها
محل ذخیره تعریف در کد یا دیتابیس فقط دیتابیس (wp_posts)
قابلیت Override بله (در نسخه‌های جدید) بله (Block Bindings)
مناسب برای صفحات فرود، بخش‌های متغیر هدر، فوتر، CTA ثابت

از منظر معماری، پترن‌ها یک لایه انتزاعی بین بلاک و صفحه ایجاد می‌کنند. به‌جای اینکه کاربر ۱۵ بلاک را دستی بچیند، یک پترن درج می‌کند و ساختار آماده را می‌گیرد. این لایه، هم سرعت تولید را افزایش می‌دهد و هم یکنواختی طراحی را تضمین می‌کند. اگر با چگونه وردپرس سایت‌ها را بدون کدنویسی ممکن کرد آشنا شده باشید، پترن‌ها را به‌عنوان یک گام تکاملی در همین مسیر می‌شناسید.

نکته مهم این است که پترن‌ها برخلاف Template Parts، در سطح محتوا ذخیره می‌شوند، نه در سطح قالب. اگر Template Part یک بخش از قالب است که در تمام صفحات تکرار می‌شود، پترن یک الگوی محتوایی است که کاربر در هر صفحه‌ای می‌تواند درج کند. این تفکیک، انعطاف‌پذیری بیشتری به تیم محتوا می‌دهد.

انواع پترن: Synced، Unsynced و Override

وردپرس سه نوع پترن را پشتیبانی می‌کند که هرکدام کاربرد متفاوتی دارند. درک این تفاوت‌ها، پیش‌نیاز انتخاب نوع مناسب است.

Unsynced Pattern (پترن ناهمگام): این نوع پترن، رایج‌ترین نوع است. وقتی کاربر یک پترن ناهمگام را درج می‌کند، یک کپی مستقل از آن ساخته می‌شود که می‌تواند آزادانه ویرایش شود. تغییرات در کد پترن، بر نمونه‌های درج‌شده اثر نمی‌گذارد. این نوع، مناسب صفحات فرود، بخش‌های متغیر، و محتوایی است که هر صفحه ممکن است تغییر کند.

Synced Pattern (پترن همگام): این نوع پترن، در دیتابیس به‌عنوان یک wp_block ذخیره می‌شود و در تمام نمونه‌ها همگام است. تغییر در یک نمونه، تمام نمونه‌ها را به‌روزرسانی می‌کند. این نوع، مناسب هدر، فوتر، CTA ثابت، و محتوایی است که باید در تمام سایت یکسان باشد.

Pattern with Overrides (پترن با قابلیت بازنویسی): این نوع، ترکیبی از دو نوع قبلی است. ساختار پترن همگام است، اما بلاک‌های خاصی می‌توانند Override شوند. برای مثال، یک پترن CTA که ساختار ثابت دارد اما متن و لینک آن در هر صفحه متفاوت است. این قابلیت از وردپرس ۶.۵ با Block Bindings معرفی شد.

// نمونه‌ای از یک پترن با Override
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
<p>محتوای پیش‌فرض که قابل بازنویسی است</p>
<!-- /wp:paragraph -->

انتخاب بین این سه نوع، یک تصمیم معمارانه است. اگر با چرا قالب‌های بلاکی آینده وردپرس هستند آشنا شده باشید، می‌دانید که این انعطاف‌پذیری، بخشی از قدرت معماری جدید وردپرس است.

ثبت پترن با PHP

ثبت پترن با PHP از طریق تابع register_block_pattern() انجام می‌شود که در Hook init فراخوانی می‌گردد. این روش، برای افزونه‌ها و قالب‌هایی که می‌خواهند پترن‌های خود را به‌صورت کد ثبت کنند، مناسب است.

<?php
add_action( 'init', 'my_plugin_register_patterns' );

function my_plugin_register_patterns() {
    register_block_pattern(
        'my-plugin/hero-section',
        array(
            'title'       => __( 'Hero Section', 'my-plugin' ),
            'description' => __( 'A hero section with heading and CTA.', 'my-plugin' ),
            'categories'  => array( 'featured', 'call-to-action' ),
            'keywords'    => array( 'hero', 'cta', 'banner' ),
            'content'     => '<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
    <!-- wp:heading {"level":1} -->
    <h1>' . esc_html__( 'عنوان اصلی', 'my-plugin' ) . '</h1>
    <!-- /wp:heading -->
    <!-- wp:paragraph -->
    <p>' . esc_html__( 'توضیح کوتاه', 'my-plugin' ) . '</p>
    <!-- /wp:paragraph -->
    <!-- wp:buttons -->
    <div class="wp-block-buttons">
        <!-- wp:button -->
        <div class="wp-block-button">
            <a class="wp-block-button__link">' . esc_html__( 'شروع کنید', 'my-plugin' ) . '</a>
        </div>
        <!-- /wp:button -->
    </div>
    <!-- /wp:buttons -->
</div>
<!-- /wp:group -->',
        )
    );
}

پارامترهای این تابع به شرح زیر است:

پارامتر نوع توضیح
title String عنوان پترن که در ویرایشگر نمایش داده می‌شود
description String توضیح کوتاه برای جستجو
categories Array دسته‌بندی‌های پترن
keywords Array کلمات کلیدی برای جستجو
content String محتوای HTML با کامنت‌های بلاک
viewportWidth Integer عرض پیشنهادی برای پیش‌نمایش
blockTypes Array بلاک‌های مورد استفاده (برای دسته‌بندی خودکار)
postTypes Array انواع پستی که پترن در آن‌ها نمایش داده شود
inserter Boolean نمایش یا عدم نمایش در Inserter
source String منبع پترن (plugin یا theme)

نکته حیاتی در ثبت پترن با PHP، استفاده از تابع ترجمه برای تمام متن‌ها است. اگر پترن شما متن ثابت دارد، باید آن را با esc_html__() یا __() ترجمه‌پذیر کنید. اگر با بین‌المللی‌سازی بلاک‌های وردپرس آشنا شده باشید، این موضوع را به‌عنوان یک الزام می‌شناسید.

ثبت پترن با فایل PHP در قالب

در قالب‌های بلاکی، یک روش استاندارد برای ثبت پترن وجود دارد: قرار دادن فایل‌های PHP در پوشه patterns/. وردپرس به‌طور خودکار این فایل‌ها را شناسایی و ثبت می‌کند:

my-theme/
├── patterns/
│   ├── hero-section.php
│   ├── pricing-table.php
│   └── testimonial.php
├── templates/
├── parts/
└── theme.json

هر فایل PHP در پوشه patterns/ شامل یک هدر Comment است که Metadata پترن را تعریف می‌کند:

<?php
/**
 * Title: Hero Section
 * Slug: my-theme/hero-section
 * Categories: featured, banner
 * Keywords: hero, cta, banner
 * Viewport Width: 1400
 * Block Types: core/post-content
 * Post Types: page, post
 * Inserter: true
 */
?>

<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
    <!-- wp:heading {"level":1} -->
    <h1><?php esc_html_e( 'عنوان اصلی', 'my-theme' ); ?></h1>
    <!-- /wp:heading -->
</div>
<!-- /wp:group -->

این رویکرد، مزایای روشنی دارد: مدیریت پترن‌ها در Git ساده‌تر است، ترجمه‌پذیری به‌صورت خودکار انجام می‌شود، و نیازی به ثبت دستی در functions.php نیست. اگر با ساختار فایل‌های یک قالب استاندارد وردپرس آشنا شده باشید، این الگو را به‌عنوان استاندارد جدید می‌شناسید.

«ثبت پترن با فایل PHP، پترن را از یک قطعه کد در functions.php به یک دارایی مستند و قابل نگهداری تبدیل می‌کند.»

ثبت پترن با JavaScript

ثبت پترن با JavaScript برای مواقعی مناسب است که پترن باید در سمت کلاینت یا در محیط ویرایشگر به‌صورت داینامیک ثبت شود. این روش، به‌خصوص در افزونه‌هایی که از @wordpress/scripts استفاده می‌کنند، رایج است.

import { registerBlockPattern } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';

registerBlockPattern( 'my-plugin/testimonial-card', {
    title: __( 'Testimonial Card', 'my-plugin' ),
    description: __( 'A single testimonial card with quote and author.', 'my-plugin' ),
    categories: [ 'text', 'testimonials' ],
    keywords: [ 'testimonial', 'quote', 'review' ],
    content: `
        <!-- wp:quote -->
        <blockquote class="wp-block-quote">
            <p>${ __( 'متن نظر مشتری', 'my-plugin' ) }</p>
            <cite>${ __( 'نام مشتری', 'my-plugin' ) }</cite>
        </blockquote>
        <!-- /wp:quote -->
    `,
} );

نکته مهم: ثبت پترن با JavaScript باید در فایل index.js افزونه یا در یک فایل جداگانه که با enqueue بارگذاری می‌شود، انجام شود. این فایل باید در Hook init ویرایشگر یا در block_editor_assets بارگذاری گردد:

<?php
add_action( 'enqueue_block_editor_assets', 'my_plugin_enqueue_patterns' );

function my_plugin_enqueue_patterns() {
    wp_enqueue_script(
        'my-plugin-patterns',
        plugins_url( 'build/patterns.js', __FILE__ ),
        array( 'wp-blocks', 'wp-i18n' ),
        '1.0.0',
        true
    );
}

تفاوت اصلی بین ثبت با PHP و JavaScript در زمان اجرا است. ثبت با PHP در سرور و قبل از بارگذاری ویرایشگر انجام می‌شود، در حالی که ثبت با JavaScript در کلاینت و پس از بارگذاری ویرایشگر اجرا می‌شود. برای اکثر موارد، ثبت با PHP توصیه می‌شود چون ساده‌تر، سریع‌تر و ترجمه‌پذیرتر است. اگر با ساخت بلاک سفارشی گوتنبرگ از صفر آشنا شده باشید، این تفاوت را به‌عنوان یک تصمیم معمارانه می‌شناسید.

دسته‌بندی پترن‌ها و مدیریت Categories

دسته‌بندی پترن‌ها (Pattern Categories) به سازماندهی پترن‌ها در ویرایشگر کمک می‌کند و تجربه کاربری را بهبود می‌بخشد. وردپرس چند دسته پیش‌فرض دارد: featured، text، gallery، call-to-action، banner، header، footer، posts، services، about، contact، team، testimonials، pricing، portfolio.

برای ثبت دسته سفارشی، از تابع register_block_pattern_category() استفاده می‌شود:

add_action( 'init', 'my_plugin_register_pattern_categories' );

function my_plugin_register_pattern_categories() {
    register_block_pattern_category(
        'my-plugin-ecommerce',
        array(
            'label'       => __( 'فروشگاهی', 'my-plugin' ),
            'description' => __( 'پترن‌های مخصوص فروشگاه اینترنتی', 'my-plugin' ),
        )
    );

    register_block_pattern_category(
        'my-plugin-saas',
        array(
            'label' => __( 'SaaS', 'my-plugin' ),
        )
    );
}

پس از ثبت، این دسته‌ها در Inserter ویرایشگر ظاهر می‌شوند و کاربر می‌تواند پترن‌ها را بر اساس آن‌ها فیلتر کند. نکته مهم در نام‌گذاری دسته‌ها، استفاده از پیشوند یکتا (مثل my-plugin-) برای جلوگیری از تداخل با دسته‌های سایر افزونه‌ها است. اگر با استفاده از استانداردهای کدنویسی وردپرس در پروژه‌ها آشنا شده باشید، این اصل را به‌عنوان یک قاعده بنیادین می‌شناسید.

دسته‌بندی خودکار بر اساس بلاک‌ها

وردپرس یک ویژگی به‌نام Block Type Auto-Categorization دارد که پترن‌ها را بر اساس بلاک‌های استفاده‌شده در آن‌ها دسته‌بندی می‌کند. برای فعال‌سازی این ویژگی، از پارامتر blockTypes در ثبت پترن استفاده کنید:

register_block_pattern(
    'my-plugin/contact-form-pattern',
    array(
        'title'       => __( 'Contact Form', 'my-plugin' ),
        'blockTypes'  => array( 'core/group', 'core/columns' ),
        'categories'  => array( 'contact' ),
        'content'     => '...',
    )
);

با این تنظیم، پترن در چند دسته به‌طور همزمان نمایش داده می‌شود: در دسته‌ای که صریحاً تعریف شده (contact) و در دسته‌های مرتبط با بلاک‌های استفاده‌شده. این ویژگی، کشف‌پذیری پترن‌ها را افزایش می‌دهد.

Pattern Overrides و بلاک‌های قابل ویرایش

Pattern Overrides یکی از قدرتمندترین ویژگی‌های جدید وردپرس است که از نسخه ۶.۵ با Block Bindings معرفی شد. این ویژگی به توسعه‌دهنده اجازه می‌دهد مشخص کند کدام بلاک‌های یک پترن همگام، در هر نمونه قابل ویرایش باشند.

<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
    <!-- wp:heading {"metadata":{"bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
    <h2>عنوان پیش‌فرض</h2>
    <!-- /wp:heading -->
    
    <!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
    <p>متن پیش‌فرض</p>
    <!-- /wp:paragraph -->
</div>
<!-- /wp:group -->

در این مثال، بلاک‌های heading و paragraph با core/pattern-overrides علامت‌گذاری شده‌اند. وقتی کاربر یک نمونه جدید از این پترن درج می‌کند، می‌تواند محتوای این دو بلاک را ویرایش کند، اما ساختار کلی پترن ثابت می‌ماند.

سه کاربرد اصلی Pattern Overrides:

  • پترن‌های شرکتی: ساختار ثابت، اما نام شرکت و لوگو در هر نمونه متفاوت
  • پترن‌های محصول: ساختار ثابت، اما نام محصول و قیمت در هر نمونه متفاوت
  • پترن‌های CTA: ساختار ثابت، اما متن و لینک فراخوان در هر نمونه متفاوت

نکته مهم: Pattern Overrides فقط در Synced Patterns کار می‌کند، چون در Unsynced Pattern هر بلاک به‌طور پیش‌فرض قابل ویرایش است. اگر با گوتنبرگ و آینده ویرایش محتوا در وردپرس آشنا شده باشید، این قابلیت را به‌عنوان یکی از گام‌های مهم تکامل گوتنبرگ می‌شناسید.

محدودیت‌های Pattern Overrides

Pattern Overrides در نسخه فعلی چند محدودیت دارد:

  • فقط برای بلاک‌های متنی (Paragraph، Heading) و تصاویر (Image) پشتیبانی می‌شود.
  • Attributeهای پیچیده مثل رنگ و فونت قابل Override نیستند.
  • در بلاک‌های داینامیک مثل Query Loop پشتیبانی نمی‌شود.
  • Override فقط در سطح Attribute کار می‌کند، نه در سطح ساختار.

با این محدودیت‌ها، Pattern Overrides برای بسیاری از سناریوهای عملی کافی است، اما در پروژه‌های پیچیده ممکن است نیاز به راه‌حل‌های جایگزین مثل بلاک‌های سفارشی داشته باشید.

پترن‌ها در قالب‌های بلاکی

در قالب‌های بلاکی، پترن‌ها نقش مهمی در تعریف تجربه کاربری دارند. قالب‌های پیش‌فرض وردپرس مثل Twenty Twenty-Four و Twenty Twenty-Five ده‌ها پترن از پیش آماده ارائه می‌دهند که کاربران می‌توانند آن‌ها را در صفحات خود درج کنند. اگر با چرا قالب‌های بلاکی آینده وردپرس هستند آشنا شده باشید، این پترن‌ها را به‌عنوان بخشی از اکوسیستم قالب می‌شناسید.

ساختار استاندارد پترن‌ها در یک قالب بلاکی:

my-theme/
├── patterns/
│   ├── hero.php
│   ├── features-grid.php
│   ├── pricing-table.php
│   ├── testimonial.php
│   └── cta-banner.php
├── templates/
│   ├── front-page.html
│   ├── single.html
│   └── archive.html
├── parts/
│   ├── header.html
│   └── footer.html
└── theme.json

هر پترن می‌تواند در یک Template یا توسط کاربر درج شود. برای درج پترن در یک Template، از بلاک core/pattern استفاده می‌شود:

<!-- wp:pattern {"slug":"my-theme/hero"} /-->
<!-- wp:pattern {"slug":"my-theme/features-grid"} /-->
<!-- wp:pattern {"slug":"my-theme/cta-banner"} /-->

این الگو، به‌ویژه در صفحات فرود و Front Page مؤثر است: صفحه از چند پترن آماده ساخته می‌شود و کاربر می‌تواند هر پترن را جایگزین یا ویرایش کند.

پترن‌های ویژه بر اساس Post Type

در قالب‌های بلاکی، می‌توان پترن‌هایی تعریف کرد که فقط برای یک Post Type خاص ظاهر شوند. این کار با پارامتر Post Types در هدر فایل پترن انجام می‌شود:

<?php
/**
 * Title: Product Feature
 * Slug: my-theme/product-feature
 * Categories: woocommerce
 * Post Types: product
 * Block Types: core/post-content
 */
?>

<!-- wp:columns -->
<div class="wp-block-columns">
    <!-- wp:column -->
    <div class="wp-block-column">
        <!-- wp:image /-->
    </div>
    <!-- /wp:column -->
    <!-- wp:column -->
    <div class="wp-block-column">
        <!-- wp:heading /-->
        <!-- wp:paragraph /-->
    </div>
    <!-- /wp:column -->
</div>
<!-- /wp:columns -->

با این تنظیم، وقتی کاربر یک محصول جدید ایجاد می‌کند، این پترن به‌صورت خودکار پیشنهاد می‌شود. این الگو، تجربه کاربری را برای تیم محتوا بهبود می‌بخشد.

پترن‌های داینامیک و شرطی

پترن‌ها به‌طور پیش‌فرض استاتیک هستند: محتوای آن‌ها در زمان ثبت تعریف می‌شود. اما در پروژه‌های واقعی، نیاز به پترن‌های داینامیک وجود دارد که محتوای آن‌ها بر اساس شرایط تغییر کند. برای این کار، از دو رویکرد استفاده می‌شود:

رویکرد اول: پترن با بلاک‌های داینامیک. به‌جای محتوای ثابت، از بلاک‌هایی استفاده کنید که محتوای خود را از دیتابیس می‌خوانند. مثلاً بلاک core/query برای نمایش آخرین نوشته‌ها، یا بلاک core/post-featured-image برای نمایش تصویر شاخص:

<!-- wp:query {"query":{"perPage":3,"postType":"post"}} -->
<div class="wp-block-query">
    <!-- wp:post-template -->
    <!-- wp:post-title /-->
    <!-- wp:post-excerpt /-->
    <!-- /wp:post-template -->
</div>
<!-- /wp:query -->

این پترن، در هر صفحه‌ای که درج شود، آخرین نوشته‌ها را نمایش می‌دهد. محتوا داینامیک است اما ساختار ثابت.

رویکرد دوم: پترن با PHP شرطی. اگر پترن با PHP ثبت می‌شود، می‌توانید محتوای آن را بر اساس شرایط محیط تغییر دهید:

function my_plugin_register_conditional_pattern() {
    $cta_text = is_user_logged_in()
        ? __( 'رفتن به داشبورد', 'my-plugin' )
        : __( 'ثبت‌نام رایگان', 'my-plugin' );

    register_block_pattern(
        'my-plugin/conditional-cta',
        array(
            'title'   => __( 'Conditional CTA', 'my-plugin' ),
            'content' => '<!-- wp:paragraph --><p>' . esc_html( $cta_text ) . '</p><!-- /wp:paragraph -->',
        )
    );
}
add_action( 'init', 'my_plugin_register_conditional_pattern' );

نکته مهم: این رویکرد، محتوای پترن را در زمان ثبت قفل می‌کند. اگر وضعیت کاربر پس از درج تغییر کند، محتوا تغییر نمی‌کند. برای محتوای واقعاً داینامیک، از Block Bindings یا بلاک‌های سفارشی استفاده کنید.

«پترن‌های داینامیک، تعادل بین استانداردسازی ساختار و انعطاف‌پذیری محتوا هستند. اگر ساختار بیش از حد ثابت باشد، کاربر احساس محدودیت می‌کند؛ اگر بیش از حد آزاد باشد، یکنواختی از دست می‌رود.»

بهینه‌سازی عملکرد پترن‌ها

پترن‌ها برخلاف بلاک‌ها، تأثیر مستقیمی بر عملکرد فرانت‌اند ندارند چون در زمان درج به بلاک‌های عادی تبدیل می‌شوند. اما دو جنبه عملکردی وجود دارد که باید در نظر گرفته شود:

جنبه اول: بارگذاری پترن‌ها در ویرایشگر. اگر تعداد پترن‌ها زیاد باشد، بارگذاری Inserter ویرایشگر کند می‌شود. برای بهینه‌سازی:

  • پترن‌های غیرضروری را با Inserter: false از Inserter پنهان کنید.
  • پترن‌های مخصوص یک Post Type را با Post Types محدود کنید.
  • پترن‌های سنگین را در فایل‌های جداگانه قرار دهید و فقط در صورت نیاز بارگذاری کنید.

جنبه دوم: تعداد پترن‌ها. اگر ده‌ها پترن در یک قالب ثبت شود، کاربر ممکن است در انتخاب دچار سردرگمی شود. توصیه می‌شود حداکثر ۲۰ تا ۳۰ پترن در یک قالب یا افزونه ثبت شود و بقیه در قالب‌های تخصصی یا افزونه‌های جداگانه قرار گیرند.

جنبه سوم: حجم HTML پترن. پترن‌های با ساختار پیچیده می‌توانند HTML زیادی تولید کنند. اگر با بهینه‌سازی HTML و کاهش حجم آن آشنا شده باشید، می‌دانید که این حجم مستقیماً بر LCP و INP اثر می‌گذارد.

معیار عملکردی تأثیر پترن راه‌حل
بارگذاری ویرایشگر کندی Inserter محدود کردن تعداد پترن‌ها
حجم HTML فرانت‌اند افزایش DOM ساده‌سازی ساختار پترن
CSS تولیدشده افزایش استایل‌ها استفاده از theme.json متمرکز
کش مرورگر بدون تأثیر پترن در زمان Build حل می‌شود

بین‌المللی‌سازی و دسترس‌پذیری پترن‌ها

پترن‌ها باید از دو جنبه مهم پشتیبانی کنند: بین‌المللی‌سازی (i18n) و دسترس‌پذیری (Accessibility). هر دو جنبه، در فرآیند ثبت پترن باید لحاظ شوند.

بین‌المللی‌سازی پترن‌ها

در ثبت پترن با PHP، تمام متن‌ها باید با توابع ترجمه علامت‌گذاری شوند:

register_block_pattern(
    'my-plugin/hero',
    array(
        'title'       => __( 'Hero Section', 'my-plugin' ),
        'description' => __( 'A hero section with CTA.', 'my-plugin' ),
        'content'     => '<!-- wp:heading --><h1>' . esc_html__( 'خوش آمدید', 'my-plugin' ) . '</h1><!-- /wp:heading -->',
    )
);

در ثبت پترن با فایل PHP در قالب، از همان توابع استفاده می‌شود. در ثبت با JavaScript، از توابع @wordpress/i18n استفاده کنید. اگر با بین‌المللی‌سازی بلاک‌های وردپرس آشنا شده باشید، این الگو برای شما آشناست.

دسترس‌پذیری پترن‌ها

پترن‌ها باید استانداردهای WCAG را رعایت کنند. این موضوع در چند سطح قابل بررسی است:

سطح اول: HTML سمنتیک. پترن‌ها باید از عناصر سمنتیک HTML استفاده کنند: <h2> برای عنوان، <ul> برای لیست، <table> برای جدول. اگر با HTML سمنتیک و اهمیت آن آشنا شده باشید، این اصل را به‌عنوان پایه دسترس‌پذیری می‌شناسید.

سطح دوم: کنتراست رنگ. اگر پترن شامل رنگ‌های سفارشی است، باید نسبت کنتراست حداقل ۴.۵:۱ را رعایت کند. اگر پترن اجازه تغییر رنگ می‌دهد، باید محدود به پالت‌های تأییدشده باشد.

سطح سوم: متن جانشین تصاویر. هر تصویر در پترن باید متن جانشین (Alt Text) داشته باشد. اگر تصویر تزئینی است، باید alt="" و aria-hidden="true" داشته باشد.

سطح چهارم: ناوبری با کیبورد. اگر پترن شامل عناصر تعاملی است (دکمه، لینک، فیلد)، باید با کیبورد قابل دسترسی باشد و Focus Indicator داشته باشد. اگر با دسترس‌پذیری در بلاک‌های وردپرس طبق WCAG آشنا شده باشید، این الزامات را به‌عنوان بخشی از کیفیت محصول می‌شناسید.

تست پترن‌ها با Jest و Playwright

تست پترن‌ها مشابه تست بلاک‌ها انجام می‌شود. با Jest، می‌توان ثبت پترن و Metadata آن را تست کرد. با Playwright، می‌توان درج پترن در ویرایشگر و رندر آن در فرانت‌اند را تست نمود.

تست ثبت پترن با Jest

import { getBlockPatterns } from '@wordpress/blocks';
import '../index';

describe( 'Pattern registration', () => {
    it( 'should register the hero pattern', () => {
        const patterns = getBlockPatterns();
        const hero = patterns.find( ( p ) => p.name === 'my-plugin/hero-section' );
        expect( hero ).toBeDefined();
        expect( hero.title ).toBe( 'Hero Section' );
        expect( hero.categories ).toContain( 'featured' );
    } );

    it( 'should have valid block content', () => {
        const patterns = getBlockPatterns();
        const hero = patterns.find( ( p ) => p.name === 'my-plugin/hero-section' );
        expect( hero.content ).toContain( 'wp:heading' );
        expect( hero.content ).toContain( 'wp:buttons' );
    } );
} );

تست درج پترن با Playwright

import { test, expect } from '@playwright/test';

test( 'should insert hero pattern in editor', async ( { page, admin, editor } ) => {
    await admin.createNewPost();
    await editor.openGlobalBlockInserter();
    await editor.searchForBlock( 'Hero Section' );
    await page.click( 'button:has-text("Hero Section")' );
    
    await expect( editor.canvas.locator( 'h1' ) ).toContainText( 'خوش آمدید' );
    await expect( editor.canvas.locator( '.wp-block-button__link' ) ).toBeVisible();
} );

این تست‌ها تضمین می‌کنند که پترن به‌درستی ثبت شده، در ویرایشگر قابل جستجو است، و در صفحه رندر می‌شود. اگر با تست بلاک‌های وردپرس با Jest و Playwright آشنا شده باشید، این الگو را به‌عنوان بخشی از استراتژی کیفیت می‌شناسید.

تست AEO و FAQ Schema

اگر پترن شما شامل بخش پرسش‌های پرتکرار است، می‌توانید FAQ Schema را در آن قرار دهید تا موتورهای جستجو و موتورهای پاسخ، محتوای آن را بهتر درک کنند:

<!-- wp:html -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "پترن سفارشی چیست؟",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "پترن سفارشی یک الگوی از پیش آماده از بلاک‌های گوتنبرگ است که با کد ثبت می‌شود."
      }
    }
  ]
}
</script>
<!-- /wp:html -->

این رویکرد، بخشی از بهینه‌سازی برای AEO (Answer Engine Optimization) است و به دیده‌شدن محتوا در نتایج غنی گوگل کمک می‌کند.

اشتباهات رایج در ثبت پترن با کد

اشتباه اول: نادیده گرفتن Hook init. تابع register_block_pattern() باید در Hook init یا پس از آن فراخوانی شود. اگر در سطح فایل یا در Hook after_setup_theme فراخوانی شود، ممکن است کار نکند.

اشتباه دوم: استفاده از متن غیرترجمه‌پذیر. اگر متن پترن با __() یا esc_html__() علامت‌گذاری نشود، در زبان‌های دیگر ترجمه نمی‌شود. این اشتباه، شایع‌ترین مشکل در پترن‌های تجاری است.

اشتباه سوم: نادیده گرفتن Prefix. نام پترن (مثل my-plugin/hero-section) باید با پیشوند یکتا شروع شود تا با پترن‌های سایر افزونه‌ها تداخل نکند. استفاده از نام‌های عمومی مثل hero منجر به تداخل می‌شود.

اشتباه چهارم: نادیده گرفتن دسته‌بندی. اگر پترن شما در هیچ دسته‌ای ثبت نشود، در Inserter در دسته «Uncategorized» ظاهر می‌شود و کاربر آن را پیدا نمی‌کند. حداقل یک دسته مناسب اختصاص دهید.

اشتباه پنجم: HTML نامعتبر در محتوا. کامنت‌های بلاک باید دقیقاً مطابق استاندارد باشند. مثلاً <!-- wp:heading --> باید بسته شود با <!-- /wp:heading -->. اگر ساختار نادرست باشد، بلاک در ویرایشگر شکسته می‌شود.

اشتباه ششم: نادیده گرفتن Escaping. هر متنی که از دیتابیس یا ورودی کاربر می‌آید، باید با esc_html() یا esc_attr() پاک‌سازی شود. اگر با پاک‌سازی داده‌ها در کدنویسی وردپرس آشنا شده باشید، این اصل را به‌عنوان یک الزام امنیتی می‌شناسید.

اشتباه هفتم: قرار دادن پترن‌های سنگین در functions.php. اگر پترن‌های زیادی در functions.php ثبت شوند، این فایل حجیم و غیرقابل نگهداری می‌شود. بهتر است هر پترن در یک فایل جداگانه در پوشه patterns/ قرار گیرد.

اشتباه هشتم: نادیده گرفتن Viewport Width. پارامتر viewportWidth تعیین می‌کند که پیش‌نمایش پترن در چه عرضی نمایش داده شود. اگر نادرست تنظیم شود، پیش‌نمایش در ویرایشگر شکسته به نظر می‌رسد.

پرسش‌های پرتکرار درباره ساخت پترن سفارشی

پترن سفارشی در وردپرس چیست و چگونه ساخته می‌شود؟

پترن سفارشی یک الگوی از پیش آماده از بلاک‌های گوتنبرگ است که با تابع register_block_pattern() در PHP یا registerBlockPattern() در JavaScript ثبت می‌شود. این تابع در Hook init فراخوانی می‌شود و پارامترهایی مثل title، categories، و content را می‌پذیرد. پترن‌ها در Inserter ویرایشگر ظاهر می‌شوند و کاربر می‌تواند آن‌ها را با یک کلیک درج کند.

تفاوت Synced Pattern و Unsynced Pattern چیست؟

Synced Pattern (پترن همگام) یک نمونه واحد است که در چندین صفحه استفاده می‌شود و تغییر آن، تمام نمونه‌ها را به‌روزرسانی می‌کند. Unsynced Pattern (پترن ناهمگام) یک الگوی اولیه است که با درج، به یک کپی مستقل تبدیل می‌شود. Synced Pattern در دیتابیس ذخیره می‌شود، در حالی که Unsynced Pattern می‌تواند در کد تعریف شود.

چگونه پترن سفارشی را در قالب بلاکی ثبت کنم؟

در قالب‌های بلاکی، پترن‌ها در پوشه patterns/ قرار می‌گیرند. هر فایل PHP شامل یک هدر Comment با Metadata پترن است: Title، Slug، Categories، Keywords، و Post Types. وردپرس به‌طور خودکار این فایل‌ها را شناسایی و ثبت می‌کند، بدون نیاز به فراخوانی دستی register_block_pattern().

آیا پترن‌ها بر سرعت سایت تأثیر می‌گذارند؟

پترن‌ها در زمان درج به بلاک‌های عادی تبدیل می‌شوند و در فرانت‌اند هیچ Overhead اضافه‌ای ایجاد نمی‌کنند. اما اگر تعداد پترن‌ها در ویرایشگر زیاد باشد، بارگذاری Inserter کند می‌شود. توصیه می‌شود حداکثر ۲۰ تا ۳۰ پترن در یک افزونه یا قالب ثبت شود.

Pattern Overrides چیست و چه کاربردی دارد؟

Pattern Overrides یک ویژگی است که از وردپرس ۶.۵ با Block Bindings معرفی شد و به توسعه‌دهنده اجازه می‌دهد مشخص کند کدام بلاک‌های یک Synced Pattern در هر نمونه قابل ویرایش باشند. این ویژگی برای پترن‌هایی مفید است که ساختار ثابت دارند اما محتوای متغیر (مثل نام محصول یا متن CTA).

آیا می‌توان پترن را از یک افزونه به قالب منتقل کرد؟

بله، اما نیازمند بازنویسی است. پترن‌های ثبت‌شده با PHP در افزونه باید به فایل‌های PHP در پوشه patterns/ قالب منتقل شوند. پترن‌های ذخیره‌شده در دیتابیس (Synced Patterns) را می‌توان با ابزارهایی مثل WP-CLI Export و Import کرد.

چگونه پترن سفارشی را به زبان‌های دیگر ترجمه کنم؟

در ثبت پترن با PHP، تمام متن‌ها باید با توابع ترجمه مثل esc_html__() علامت‌گذاری شوند. سپس فایل POT با ابزار wp i18n make-pot تولید می‌شود و مترجم‌ها آن را به زبان‌های مختلف ترجمه می‌کنند. در ثبت با JavaScript، از توابع @wordpress/i18n استفاده کنید.

آیا پترن‌ها با WooCommerce سازگار هستند؟

بله، WooCommerce از نسخه ۸ به بعد پترن‌های اختصاصی برای محصولات، سبد خرید و Checkout ارائه می‌دهد. می‌توانید پترن‌های سفارشی برای صفحات محصول بسازید و با Post Types: product آن‌ها را به محصولات محدود کنید.

چگونه پترن سفارشی را در مخزن وردپرس منتشر کنم؟

پترن‌ها بخشی از یک افزونه یا قالب هستند و به‌تنهایی منتشر نمی‌شوند. برای انتشار، افزونه یا قالبی که پترن را ثبت می‌کند، باید در مخزن رسمی ارسال شود. اگر با انتشار بلاک سفارشی در مخزن وردپرس آشنا شده باشید، این فرآیند را به‌عنوان بخشی از استراتژی انتشار می‌شناسید.

آیا پترن‌ها در ویرایشگر Classic کار می‌کنند؟

خیر، پترن‌ها فقط در ویرایشگر گوتنبرگ و Site Editor قابل استفاده هستند. در ویرایشگر Classic، گزینه‌ای برای درج پترن وجود ندارد. اگر سایت شما از ویرایشگر Classic استفاده می‌کند، باید به گوتنبرگ مهاجرت کنید. اگر با مقایسه ویرایشگر Classic و گوتنبرگ آشنا شده باشید، این محدودیت را به‌عنوان یکی از دلایل مهاجرت می‌شناسید.

نگاه راهبردی به پترن‌های سفارشی

پترن‌های سفارشی یکی از قدرتمندترین ابزارهای وردپرس برای استانداردسازی طراحی، افزایش سرعت تولید محتوا، و تضمین یکنواختی در مقیاس هستند. سه معیار کلیدی برای موفقیت در این حوزه:

۱. طراحی از ابتدا با تفکر پترن. به‌جای ساخت هر صفحه به‌صورت مستقل، ساختارهای تکرارشونده را شناسایی کنید و آن‌ها را به پترن تبدیل نمایید. این رویکرد، بدهی فنی طراحی را کاهش می‌دهد.

۲. ترکیب PHP و JavaScript در جای مناسب. برای اکثر پترن‌ها، ثبت با PHP در پوشه patterns/ بهترین انتخاب است. JavaScript فقط برای پترن‌هایی مناسب است که نیاز به منطق سمت کلاینت دارند.

۳. رعایت i18n، دسترس‌پذیری و تست. پترن‌ها باید از ابتدا با ترجمه‌پذیری، دسترس‌پذیری و تست خودکار طراحی شوند. این سه، نه ویژگی‌های اضافی، بلکه بخشی از تعریف «تمام‌شده» هستند.

در پروژه‌های واقعی، پترن‌ها می‌توانند تفاوت محسوسی در بهره‌وری تیم محتوا ایجاد کنند. اگر با گوتنبرگ و تحول ویرایش محتوا در وردپرس آشنا شده باشید، این ابزار را به‌عنوان یک گام تکاملی در جهت دموکراتیک‌سازی طراحی وب می‌شناسید.

تحلیل مهندسی سطح پیشرفته

از منظر معماری نرم‌افزار، پترن‌ها یک نمونه از Composition over Inheritance هستند: به‌جای ارث‌بری از یک قالب پایه، ساختارها را از ترکیب بلاک‌های کوچک می‌سازید. این رویکرد، مزایای روشنی دارد: کاهش پیچیدگی، افزایش قابلیت بازاستفاده، و جداسازی بهتر بین ساختار و محتوا. چالش اصلی، Versioning Pattern Definitions است: وقتی یک پترن در کد تغییر می‌کند، نمونه‌های درج‌شده در دیتابیس تحت تأثیر قرار نمی‌گیرند. این یعنی توسعه‌دهنده باید تصمیم بگیرد که آیا تغییرات را فقط برای نمونه‌های جدید اعمال کند یا نمونه‌های موجود را نیز به‌روزرسانی نماید. راه‌حل استاندارد، استفاده از Synced Patterns برای محتوای ثابت و Unsynced Patterns برای محتوای متغیر است. چالش دوم، Test Coverage است: تست پترن‌ها نیازمند یک استراتژی چندلایه است: تست ثبت با Jest، تست درج با Playwright، و تست رندر با تست‌های بصری. اگر با تست بلاک‌های وردپرس با Jest و Playwright آشنا شده باشید، این رویکرد را به‌عنوان بخشی از بلوغ مهندسی می‌شناسید. در مقیاس بزرگ، مدیریت ده‌ها پترن در چند پروژه نیازمند یک Design System متمرکز است که در آن، هر پترن یک Component از یک کتابخانه مشترک باشد. این رویکرد، در آژانس‌های طراحی و شرکت‌های چندمحصولی رایج است و به‌عنوان Pattern Library شناخته می‌شود.

اگر این تجربه را در یک پروژه واقعی داشته‌اید، جالب است بدانید کدام بخش از ساخت پترن سفارشی بیشترین زمان را از شما گرفت. تجربه خودتان را در دیدگاه‌ها بنویسید؛ به‌خصوص اگر راه‌حل دیگری پیدا کرده‌اید که می‌تواند برای خواننده بعدی مفید باشد. 🧩

همچنین اگر می‌خواهید در مورد پیاده‌سازی عملی بلاک‌ها و پترن‌ها بیشتر بدانید، ساخت بلاک سفارشی گوتنبرگ از صفر و راهنمای ساخت بلاک سفارشی گوتنبرگ می‌توانند نقاط شروع خوبی باشند.