【WordPress】自作ブロック作成手順

WordPressでブロックを作成する方法には、主に2つのアプローチがあります

1)プラグインとして作成する方法:

  • 独立したプラグインとしてブロックを開発します。
  • メリット:
    • サイト全体で使用可能
    • テーマに依存しない
    • 他のWordPressサイトでも再利用しやすい
  • デメリット:
    • プラグイン管理が必要
    • テーマとの統合が緩やか

2)テーマの一部として作成する方法:

  • 現在使用しているテーマの機能としてブロックを組み込みます。
  • メリット:
    • テーマと密接に統合できる
    • サイトのデザインに合わせやすい
    • 追加のプラグイン管理が不要
  • デメリット:
    • テーマを変更すると失われる可能性がある
    • 他のサイトでの再利用が難しい

テーマの一部としてブロック作成

  1. JavaScriptでブロックを定義
  2. functions.phpで上記を読み込む

1)JavaScriptでブロックを定義する

wp-content
└─ themes
    └─ mytheme //独自テーマのディレクトリ
        ├── functions.php        // ✅JavaScriptを読み込む
        ├── ...
        └─ js / assetes
                    └─ sample_block_01.js   // ✅ブロックを登録

▽sample_block_01.js

(function (blocks, element) {
    var el = element.createElement; // React要素を作成するためのヘルパー関数
  
    // ✅カスタムブロックの登録
    blocks.registerBlockType(
      "my-blocks/sample-block", // 任意の名前空間 / ブロック名
      {
              // ✅各種設定
        title: "サンプルブロック", // タイトル(エディタ上で表示される)
        icon: "heart", // アイコン(https://developer.wordpress.org/resource/dashicons/#heart から選べる)
        description: "これはテスト用のブロックです", // 説明
        category: "common", // カテゴリ(ブロックを選択するときの分類)
        example: {}, // プレビューを表示する設定
  
        // ✅投稿編集ページでの見え方:<h2 style="省略">これはサンプルブロックです。(edit)</h2>
        edit: () =>
          el(
            // h2タグで囲む
            "h2",
  
            // h2タグの属性
            {
              style: {
                backgroundColor: "#ff83003b",
                color: "black",
                lineHeight: "200px",
                textAlign: "center",
                fontSize: "20px",
                margin: "100px 0 100px 0",
                position: "relative",
              },
            },
  
            // h2タグの中身
            [
              "これはサンプルブロックです。(edit)test",
            ]
          ),
  
        // ✅サイトに表示されるときの見え方:<div>これはサンプルブロックです。(save)</div>
        save: () =>
          el(
            // divタグで囲む
            "h2",
  
            // divタグの属性
            {
              style: {
                backgroundColor: "#ff83003b",
                color: "black",
                lineHeight: "200px",
                textAlign: "center",
                fontSize: "20px",
                margin: "100px 0 100px 0",
                position: "relative",
              },
            },
  
            // divタグの中身
            [
              "これはサンプルブロックです。(save)",
            ]
          ),
      }
    );
  })(window.wp.blocks, window.wp.element);

2)functions.phpでJavaScriptを読み込む

▽functions.php

<?php
// 20240714 ✅ブロック用のスクリプトを登録する関数
function add_sample_block() {
    //ブロック用のスクリプトを登録し、出力用のキューに入れる
    wp_enqueue_script(
        'sample_block_script', //スクリプトを識別するためのハンドル名
        get_stylesheet_directory_uri() . '/assets/js/sample_block_01.js',  //スクリプトの URL
        array( 'wp-blocks', 'wp-element' ) //✅依存スクリプト
    );
}
// ✅アクションフックに登録
add_action( 'enqueue_block_editor_assets', 'add_sample_block' );

これはサンプルブロックです。(save)

wp_register_script

wp_register_script は WordPress の関数で、JavaScript ファイルを「WordPressに登録する」ために使用します。

wp_register_script( $handle, $src, $deps, $ver, $in_footer );
  • $handle: スクリプトのハンドル(識別子)。一意の名前を指定します。
  • $src: スクリプトファイルのURL。
  • $deps: このスクリプトが依存する他のスクリプトのハンドルを配列で指定します。オプションです。
  • $ver: スクリプトのバージョン。オプションです。
  • $in_footer: スクリプトをページのフッターで読み込むかどうかを真偽値で指定します。オプションです。デフォルトは false

register_block_type

register_block_type は、WordPress のブロックエディタ(Gutenberg)で使用する独自ブロックを登録するための関数です。

register_block_type( $block_type, $args );
  • $block_type: ブロックの名前空間とブロック名をスラッシュで区切った文字列。例えば、'my-plugin/my-block' のように指定します。※名前空間は、プラグインやテーマの名前、識別子。
  • $args: ブロックの設定を含む連想配列。オプションです。

$args 配列で指定できる主なオプションは以下の通りです。

  • render_callback: ブロックの動的なレンダリングを行うPHP関数を指定します。
  • attributes: ブロックの属性(ユーザーが編集可能な設定)を定義します。
  • editor_script: ブロックエディタ内で使用するJavaScriptファイルを指定します。
  • editor_style: ブロックエディタ内で使用するCSSファイルを指定します。
  • style: フロントエンドで使用するCSSファイルを指定します。

プラグインとして作成

1)プラグインのディレクトリ作成

wp-content/plugins/ 「」

2)1)で作成したディレクトリにファイルを作成

wp-content
└── plugins
    └── my-first-block //新規に作成するプラグインのディレクトリ
        ├── my-first-block.php  //プラグインファイル
        └── block.js  //ブロック用のスクリプト

▽my-first-block.php

<?php
/*
Plugin Name: My First Block
*/

function my_first_block_enqueue() {
    //ブロック用のスクリプトを wp_register_script で登録
    wp_register_script(
      //スクリプトを識別するためのハンドル名
      'my-first-block-script',
      //スクリプトの URL
      plugins_url( 'block.js', __FILE__ ),
      //依存するスクリプト
      array( 'wp-blocks', 'wp-element' )
    );
   
    //ブロックタイプの登録
    register_block_type(
      //namespace を含むブロックタイプの名前
      'my-blocks/my-first-block',
      array(
        //ブロックのスクリプト block.js をエディタ用スクリプトとして関連付け
        //上記 wp_enqueue_script で登録したハンドル名 my-first-block-script を指定
        'editor_script' => 'my-first-block-script',
      )
    );
  }
  add_action( 'init', 'my_first_block_enqueue' );

▽block.js

( function( blocks, element ) {
    var el = element.createElement;
   
    //スタイルをオブジェクト形式 { } で記述して変数に代入(23、30行目で参照)
    var blockStyle = {
      backgroundColor: '#900', //キャメルケース(区切りはカンマ)
      color: '#fff',
      padding: '20px',
    };
   
    //registerBlockType でブロックを登録
    blocks.registerBlockType(
      //namespace を含むブロックの名前 namespace/block-name
      'my-blocks/my-first-block',
      //ブロックのプロパティ(動作を定義するオブジェクト)
      {
        title: 'My First Block Sample',
        icon: 'universal-access-alt',
        category: 'layout',
        edit: function() {
          return el(
            'p',
            { style: blockStyle },  //インラインスタイル(style属性)でスタイル(5行目)を指定
            'Hello World, sample 01 (edit/エディタ用).'
          );
        },
        save: function() {
          return el(
            'p',
            { style: blockStyle },
            'Hello World, sample 01 (save/フロントエンド用).'
          );
        },
      }
    );
  }(
    window.wp.blocks,
    window.wp.element
  ) );

3)プラグイン有効化

4)編集画面から独自ブロックを追加

Hello World, sample 01 (save/フロントエンド用).

@wordpress/scriptsを使用した場合

1)プラグインディレクトリを作成

npm install --save-dev @wordpress/scripts

2)package.jsonを編集

"scripts": {
    "start": "wp-scripts start",
    "build": "wp-scripts build"
}

↓作成したブロック

Hello World, step 1 (from the frontend).

3)ビルド元のファイルを作成

↓ \wp-content\plugins\my-custom-block02\src\index.jsx
(my-custom-block02はプラグインディレクトリ)

const { registerBlockType } = wp.blocks;
 
const blockStyle = {
    backgroundColor: 'indigo',
    color: '#fff',
    padding: '20px',
};
 
registerBlockType( 'gutenberg-examples/example-01-basic-esnext', {
    title: 'Example: Basic (esnext)',
    icon: 'universal-access-alt',
    category: 'layout',
    edit() {
        return <div style={ blockStyle }>Hello World, step 1 (from the editor).</div>;
    },
    save() {
        return <div style={ blockStyle }>Hello World, step 1 (from the frontend).</div>;
    },
} );

4)ビルドする

npm run build

5)phpファイル作成

<?php
/**
 * Plugin Name: My Custom Block 02
 * Description: A custom block plugin 02
 * Version: 1.0
 * Author: Your Name
 */

defined( 'ABSPATH' ) || die();

function gutenberg_examples_01_register_block() {
    wp_register_script(
        'gutenberg-examples-01',
        plugins_url( 'build/index.js', __FILE__ ), 
        array( 'wp-blocks', 'wp-element' )
    );

    register_block_type( 'gutenberg-examples/example-01-basic-esnext', array(
        'editor_script' => 'gutenberg-examples-01',
    ) );
}
add_action( 'init', 'gutenberg_examples_01_register_block' );

6)「TypeError: Cannot read properties of undefined (reading ‘jsx’) at save…」

エラー原因

プラグインを有効化しWordPress編集画面でブロックを選択したところエラー発生

「TypeError: Cannot read properties of undefined (reading ‘jsx’) at save…」

このエラーメッセージは、index.js ファイルの中で jsx プロパティが未定義のオブジェクトにアクセスしようとしていることを示しています。具体的には、save 関数内で発生しているようです。

ビルドされた index.js ファイルを見ると、ReactJSXRuntime オブジェクトが window オブジェクトから参照されています。

↓\build\index.js

const e=window.ReactJSXRuntime

しかし、window.ReactJSXRuntime は定義されていないため、eundefined になります。その結果、e.jsx 関数呼び出しが TypeError を引き起こしています。

エラー解決方法

プラグインディレクトリにbabel.config.jsを作成

module.exports = {
    presets: ['@wordpress/default'],
    plugins: [
      ['@babel/plugin-transform-react-jsx', {
        pragma: 'wp.element.createElement',
        pragmaFrag: 'wp.element.Fragment',
      }],
    ],
  };

→React JSX 構文を WordPress の wp.element.createElement 関数に変換するため

package.jsonを編集

"devDependencies": {
  "@babel/plugin-transform-react-jsx": "^7.14.9",
  "@wordpress/babel-preset-default": "^7.0.0",
  "@wordpress/scripts": "^28.3.0"
}

変更を保存し、npm install コマンドを実行して新しい依存関係をインストールします。npm run build コマンドを実行して、プロジェクトを再ビルドします。

再ビルド後、生成された index.js ファイルに window.ReactJSXRuntime への参照がなくなり。wp.element.createElement が使用されています。

「WordPress JSX」、「@wordpress/scripts」を使った Gutenberg ブロックの作り方

WordPress JSX を使った Gutenberg ブロックの作り方
https://www.webdesignleaves.com/pr/wp/wp_block_basic_jsx.html

1)package.json作成

PS C:\ida_test\docker-wp-test_0709\html\wp-content\themes\swell_child\block-dev> npm init -y

npm init

これは新しい package.json ファイルを作成するための基本コマンドです。

-y フラグ: これは “yes” の略で、全てのプロンプトに自動的に “yes” と答えることを意味します。

2)@wordpress/scripts をインストール

$ npm install --save-dev --save-exact @wordpress/scripts

WordPress用の開発スクリプトをプロジェクトにインストールするものです。

  1. npm install: Node.jsパッケージをインストールするためのコマンドです。
  2. --save-dev: このフラグは、パッケージを開発依存関係(devDependencies)としてインストールすることを指示します。つまり、このパッケージは開発時にのみ必要で、本番環境では必要ないことを意味します。
  3. --save-exact: このフラグは、パッケージの正確なバージョンをpackage.jsonファイルに保存することを指示します。これにより、異なる環境で同じバージョンのパッケージが使用されることが保証されます。
  4. @wordpress/scripts: これはインストールするパッケージの名前です。このパッケージはWordPressの開発に役立つ様々なスクリプトやツールを提供します。

このパッケージをインストールすることで、以下のような利点があります:

  • モダンなJavaScript開発環境のセットアップ(Babel, webpack, ESLintなど)
  • コードのビルド、テスト、リント(構文チェック)のためのNPMスクリプト
  • WordPressプロジェクト用の最適化された設定

3)ビルド用コマンドを追加

▽package.json

{
  "name": "block-dev",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "wp-scripts start",
    "build": "wp-scripts build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@wordpress/scripts": "28.3.0"
  }
}

4)デフォルトのエントリポイントの名前と出力先を変更

webpack の設定を拡張します。

独自の webpack.config.js という名前のファイルを作成し、package.json と同じ階層に配置します

▽\wp-content\themes\swell_child\block-dev\webpack.config.js

const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
const path = require('path');
 
module.exports = {
  //先頭で取得した既存の設定をスプレッド構文(...)で以下に展開
  ...defaultConfig,
  // 既存の設定を上書き

  // Webpackのエントリーポイントを設定しています。
  // この場合、'my-block-01'という名前のエントリーポイントが./src/my-block-01.jsファイルを指しています。
  entry: {
    'my-block-01': './src/my-block-01.js'
  },

  // 出力設定を指定しています:
  // path: ビルドされたファイルが出力されるディレクトリを指定。
  // filename: 出力されるファイルの名前を指定。[name]はエントリーポイントの名前に置き換えられます。
  output: {
    path: path.join(__dirname, '../my-blocks/build'),
    filename: '[name].js'
  }
}

この設定により:

WordPressのデフォルトのwebpack設定が基本として使用されます。
カスタムブロック(’my-block-01’)のソースファイルが指定されています。
ビルドされたファイルは../my-blocks/buildディレクトリに出力されます。
出力ファイルの名前は、エントリーポイントの名前(この場合’my-block-01’)に基づいて生成されます。

5)ブロックを定義するファイル(my-block-01を作成

import { registerBlockType } from '@wordpress/blocks';
 
registerBlockType( 'my/block-01', {
  title: 'Sample Block 01',
  icon: 'smiley',
  category: 'layout',
  edit: () => <div>Hello World! (Edit)</div>,
  save: () => <div>Hello World! (Save)</div>,
} );

6)ビルドを実行

block-dev> npm run build

「my-block-01.js」、「my-block-01.asset.php」が出力先の my-blocks/build に自動的に生成されます。

7)phpファイルで定義したブロックを読み込む

1)\my-blocks\php\register-my-block-01.phpの作成

<?php
function my_block_01_enqueue() {
  //アセットファイルをインクルードして変数に保存
  $asset_file = include( get_theme_file_path('/my-blocks/build/my-block-01.asset.php'));
 
  //ブロック用のスクリプトを登録
  wp_register_script(
    'my-block-01',
    get_theme_file_uri('/my-blocks/build/my-block-01.js'),
    $asset_file['dependencies'], //依存スクリプトの配列
    $asset_file['version'] //バージョン
  );
 
  //ブロックタイプの登録
  register_block_type(
    'my/block-01',
    array(
      //エディター用スクリプトとしてブロック用スクリプトを指定(登録)
      'editor_script' => 'my-block-01',
    )
  );
}
add_action( 'init', 'my_block_01_enqueue' );

2)functions.phpを編集

include( get_theme_file_path('/my-blocks/php/register-my-block-01.php'));

表示されない…?

参考サイト

WordPress JSX を使った Gutenberg ブロックの作り方
https://www.webdesignleaves.com/pr/wp/wp_block_basic_jsx.html

【基礎知識まとめ】WordPressでブロックを自作する方法
https://rakuraku-engineer.com/posts/wp-block-custom/

WordPress Gutenberg ブロックの作成
https://www.webdesignleaves.com/pr/wp/wp_block_basic.html