ブログ

PHPだけでカスタムブロックを作成。古いショートコードよ、さらば 🥳

David Wang
著者: David Wang ·

WordPress 5.0がブロックエディターを導入して以来、Gutenbergブロックの構築にはReact、Node.js、そしてビルドパイプラインが必要でした。PHPを専門とする方 — 私自身を含め、多くのWordPress開発者がそうであるように — にとって、その障壁はほぼ10年間にわたって参入を阻んできました。WordPress 7.0がこれを変えます。PHPのみのブロックでは、1つのPHPファイルとautoRegisterフラグだけで、完全に機能するGutenbergブロックを登録できます。

PHPを書くだけで、ブロックが手に入ります。ツール不要。ビルド不要。🥳 この記事では、PHPのみのブロックの仕組みを説明し、クラシックなショートコードをブロックに置き換える実際の例を紹介します。

PHPのみのブロックとは?

これまでカスタムGutenbergブロックを作成するには、JavaScriptツールチェーンのセットアップが必要でした。npm installblock.jsonファイル、webpack.config.js@wordpress/scriptsによるビルドステップ、そしてJSXで書かれたedit.jsコンポーネントです。変更のたびに、エディターで確認する前にコンパイルが必要でした。シンプルな表示ブロックを登録したいだけのPHP開発者にとって、そのオーバーヘッドは常にタスクに不釣り合いなものでした。

PHPのみのブロックはそのすべてを解消します。register_block_type()'autoRegister' => trueを渡すだけで、WordPressがServerSideRenderを使ってJavaScript側のすべてを自動的に処理します。ブロックはインサーターに表示され、キャンバスにライブプレビューが描画され、サイドバーにインスペクターコントロールが生成されます — すべてJavaScriptのコードを1行も書かずに。

コントロールは属性タイプに基づいて自動生成されます:

属性タイプ生成されるインスペクターコントロール
stringテキスト入力
integer / number数値入力
booleanトグル
string + enumドロップダウン選択

自動生成されるコントロールは現時点では上記の4つのタイプのみをカバーしています。画像ピッカー、メディアアップロード、ネストされたデータなど、より複雑なものはまだサポートされておらず、JavaScriptで登録されたブロックが必要になります。また、開発者は個別の属性にlocalロールを付けて内部状態としてマークすることができます。WordPressはサイドバーコントロールを構築する際にそれらをスキップします。

PHPのみのブロックは、追加の依存関係なしにWordPress 7.0で今日から利用できます。Make WordPress Coreの公式開発者ノートをご覧ください。

これは誰のためのものですか?

JavaScriptの深い専門知識を持たない小規模エージェンシーやフリーランサーは、ビルドパイプラインに触れることなく、WordPressのネイティブ機能をフルに活用したブロックエディターソリューションを構築できるようになりました。ショートコードに頼るのではなく、著者ボックス、プルクォート、お客様の声、CTAバナー、お知らせなどのテーマ固有のカスタムGutenbergブロックを提供したい場合、PHPのみのブロックはその障壁を大幅に下げる助けになります。

インラインリッチテキスト編集、リアルタイムのリアクティブUI、またはインナーブロックのネストが必要な場合は、JavaScriptで登録されたブロックの代替にはなりません — しかし、構造化された表示ブロックの多くのケースでは、最適な選択肢となります。

従来の方法:ショートコード

PHPのみのブロックが登場する以前、PHP開発者の現実的なアプローチはショートコードでした。著者名、会社名、星の評価という3つの属性と、レビューテキスト用のインナーコンテンツを持つシンプルなお客様の声ショートコードの例です:

function testimonial_shortcode( $atts, $content = '' ) {
    $atts = shortcode_atts( [
        'name'    => '',
        'company' => '',
        'stars'   => 5,
    ], $atts );
 
    $stars_count = max( 1, min( 5, intval( $atts['stars'] ) ) );
    $stars_html  = str_repeat( '★', $stars_count )
                 . str_repeat( '☆', 5 - $stars_count );
 
    return sprintf(
        '<blockquote class="testimonial">
            <p class="testimonial__stars">%s</p>
            <p class="testimonial__body">%s</p>
            <footer class="testimonial__attribution">
                <strong>%s</strong>%s
            </footer>
        </blockquote>',
        esc_html( $stars_html ),
        wp_kses_post( $content ),
        esc_html( $atts['name'] ),
        $atts['company'] ? ', ' . esc_html( $atts['company'] ) : ''
    );
}
add_shortcode( 'testimonial', 'testimonial_shortcode' );

使用例:

[testimonial name="Sarah K." company="Acme Corp" stars="4"]
	Saved us hours every week.
[/testimonial]

動作はします...でも、ただのショートコードです 🤷🏻‍♂️

ショートコードの問題点をいくつか挙げてみましょう:

  • エディターでは見えない。 著者はエディターで[testimonial name="Sarah K." ...]というコードを見るだけで、レンダリングされたカードは見えません。プレビューがありません。
  • 発見しにくい。 ショートコードの存在を知っていて、パラメーター名を覚えていなければなりません。UIには何も表示されません。
  • ネイティブのスタイルコントロールがない。 色、スペーシング、タイポグラフィを調整するにはカスタムCSSか手動で追加の属性が必要です。
  • インナーコンテンツはリッチテキストではない。 レビュー本文は$contentにプレーンな文字列として渡されます — 編集可能なリッチテキストエリアではありません。

ショートコードはその時代に適したツールでした。ブロックエディターはより良いものを提供しますが、活用が難しい状況でした。WordPress 7.0はPHPのみのブロックという形でショートカットを提供します。

明確にしておくと:Gutenbergブロックを構築する正しい新しい方法は、依然として完全なeditコンポーネントを持つJavaScriptで登録されたブロックです。PHPのみのブロックは簡略化されたパスであり、キャンバス上でのリッチ編集を必要としないサーバーレンダリングブロックに意図的に限定されています。JavaScriptブロックの代替ではなく、ビルドパイプラインとReactコンポーネントのオーバーヘッドが正当化されないシンプルなユースケース向けの新しい選択肢です。

よりシンプルな選択肢:PHPのみのブロック

PHPだけで同じお客様の声をWordPressカスタムブロックとして構築してみましょう。レシピは:supports'autoRegister' => trueを指定したregister_block_type()render_callbackです。

ブロックの完全なコードはこちらです:

function my_plugin_register_testimonial_block() {
    register_block_type(
        'my-plugin/testimonial', // Block name: namespace/slug
        array(
            'title'      => 'Testimonial', // Shown in the block inserter
            'attributes' => array(
                // string attributes generate a text input in the sidebar
                'name'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                'company' => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                // integer attributes generate a number input
                'stars'   => array(
                    'type'    => 'integer',
                    'default' => 5,
                ),
                'body'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
            ),
            // render_callback is the PHP function that outputs the block's HTML
            'render_callback' => function ( $attributes ) {
                $stars_count = max( 1, min( 5, intval( $attributes['stars'] ) ) );
                $stars_html  = str_repeat( '★', $stars_count )
                             . str_repeat( '☆', 5 - $stars_count );
 
                // Translatable string for screen readers — standard WordPress i18n, nothing extra needed
                /* translators: %d: star rating out of 5 */
                $stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );
 
                return sprintf(
                    '<blockquote %s>
                        <p class="testimonial__stars" aria-label="%s">%s</p>
                        <p class="testimonial__body">%s</p>
                        <cite class="testimonial__attribution">
                            <strong>%s</strong>%s
                        </cite>
                    </blockquote>',
                    // Merges your class with editor-added colour, spacing, and typography styles
                    get_block_wrapper_attributes( array( 'class' => 'testimonial wp-block-quote' ) ),
                    esc_attr( $stars_label ),
                    esc_html( $stars_html ),
                    wp_kses_post( $attributes['body'] ),
                    esc_html( $attributes['name'] ),
                    $attributes['company'] ? ', ' . esc_html( $attributes['company'] ) : ''
                );
            },
            'supports' => array(
                // The key flag — tells WordPress to handle JS registration automatically
                'autoRegister' => true, 
                // The rest unlock native colour, typography, and spacing panels in the sidebar
                'color'      => array(
                    'background' => true,
                    'text'       => true,
                ),
                'typography' => array(
                    'fontSize' => true,
                ),
                'spacing'    => array(
                    'padding' => true,
                    'margin'  => true,
                ),
            ),
        )
    );
}
add_action( 'init', 'my_plugin_register_testimonial_block' );

結果:

PHPのみで作成されたWordPressカスタムブロックの例
自動生成されたコントロールとエディターキャンバスのライブプレビューを持つPHPのみのお客様の声ブロックと、ショートコード版の比較。

いくつか注目すべき点があります。まず、ショートコードのインナーコンテンツは、PHPのみのブロックでは直接対応するものがありません。レビュー本文はサイドバーのインスペクターコントロールから編集できるstring属性になります — キャンバス上の編集可能なリッチテキストエリアではなく、1行のテキストフィールドです。短いお客様の声の引用ならこれで問題ありません。より長い本文テキストには、RichTextコンポーネントを持つJavaScriptで登録されたブロックが必要になります。

次に、get_block_wrapper_attributes()はあなたのクラスと、エディターが色、タイポグラフィ、スペーシングのために追加するものを統合します — そのため、追加のCSSなしでネイティブのスタイルパネルが機能します。render_callbackはユーザーが設定した値のみを含む$attributes配列を受け取ります。インナーコンテンツがサポートされていないため、$contentパラメーターはありません。

ショートコード版と比べて得られるもの:

  • エディターキャンバスでのライブプレビュー。 生のショートコード構文はもう不要です — 著者は編集しながらレンダリングされたお客様の声カードを確認できます。
  • 自動生成されたコントロール。 名前、会社名、本文(テキスト入力)、星(数値入力)がサイドバーのインスペクターコントロールに自動的に表示されます。
  • ネイティブの色、フォント、スペーシングパネル。 supportsから提供されます — カスタムCSSは不要です。
  • 発見しやすい。 ブロックはインサーターにその名前とアイコンで表示されます。

最初から翻訳対応

PHPのみのブロックを使用する際には、2つの異なる翻訳上の懸念があります。どちらがどちらかを明確にしておく価値があります。

1つ目は、PHPテンプレートに埋め込まれた静的な文字列 — ラベル、ボタンテキスト、UIコピーです。これらは通常のWordPressのPHPファイルと同様に__()_e()で処理されます。上のブロックでは、星のラベルがその例です:

/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );

標準のWordPressツールがこれらを自動的に検出します。追加の設定は不要です。

2つ目の懸念は、ブロック属性として保存されるユーザー入力コンテンツ — お客様の声の本文、レビュアーの名前、会社名です。これはエディターが実際にブロックに入力するコンテンツであり、__()はそれに触れません。多言語サイトでは、これらの属性値を各言語に個別に翻訳する必要があり、それはWordPressが単独で処理するものではありません。

Gato AI Translations for PolylangはPHPのみのブロックをすぐにサポートしています。Gutenberg、Bricks、Elementor、その他のページビルダーをサポートするのと同じ方法で。追加のセットアップは必要ありません。

すべてのstring属性は翻訳のために自動的に登録されます。特定のフィールドを翻訳すべきでない場合 — 内部参照、URL、文字列として保存された数値コード — フィルターを使用してオプトアウトできます。

この記事のお客様の声ブロックでは、レビュアーの名前、会社名、本文テキストはすべてプラグインをインストールするだけで自動的に翻訳されます。

PHPのみのブロックでできないこと(現時点では)

PHPのみのブロックの現在の制限:

  • インナーブロックやネストはできない。 PHPのみのブロックの内部に他のブロックを配置することはできません。
  • キャンバス上のリッチテキスト編集はできない。 RichTextコンポーネントにはJavaScriptが必要です。テキストコントロールはサイドバーのテキストフィールドとしてのみレンダリングされます。
  • サイドバーの文字列フィールドは1行のみ。 string属性はTextareaControlではなくTextControlになります — 長いテキストには不向きです。
  • 画像やメディアピッカー属性はない。 画像/ファイルアップロードのサポートはBlock Fields APIを通じて後のリリースで予定されています。
  • エディタープレビューに往復の遅延がある。 属性の変更はサーバーで再レンダリングするためにREST APIリクエストをトリガーするため、プレビューは即座に更新されません。

シンプルな構造化ブロック — お客様の声、CTA、お知らせ、著者プロフィール、ビジネスリスティング — にとって、PHPのみのブロックは最適な選択です。キャンバス上でのリッチ編集が必要なものには、JavaScriptの登録が引き続き適切なツールです。

今後の展開

WordPress 7.0のPHPのみのブロックにより、ブロック開発はすべてのPHP開発者の手の届くところに来ました。PHPファイル1つ、register_block_type()の呼び出し1回で、サイドバーコントロール、ライブキャンバスプレビュー、ネイティブスタイルサポートを持つ完全に機能するGutenbergブロックが手に入ります。PHPを書くだけで、ブロックが手に入ります。ツール不要。ビルド不要。JavaScriptも不要。

多言語サイトを構築しているなら、Gato AI TranslationsはPHPのみのブロックとシームレスに連携します — コンテンツは初日から翻訳可能です。

さらに進みたいですか?


次に来るものをチェック

ニュースレターを購読しましょう。新バージョンのリリース、新しいプラグインの公開、お知らせがある際にお伝えします。