前回のtheme.json解読に続き、今回はブロックを自作してみようと思います。
ブロックはプラグインとしてインストールする作り方とテーマとして動作する作り方があります。
テーマとして動作させる
必要なコードをfunctions.phpに書き、テーマを有効化したらブロックが使えるようになっている
通常のプラグインでも同じ処理を使用テーマのfunctions.phpに書けば同じ動きをしますので、それと同じです。
テーマに依存しないようにプラグインとして作成することが推奨されていますので、今回はその方法でやってみます。
目次
@wordpress/create-blockというツールで基本的な雛形を対話式で生成することができます。
ADs
まずは事前にNode.jsのインストールが必要です。
Node.jsはバージョンによってあっちが動いたけどこっちは動かない…ということが多々あるのでバージョン管理ツールを使うのがお勧めです。
私はnvmというツールを使用しています。
1.コマンドプロンプトで以下のコマンドを入力します。
1 |
npx @wordpress/create-block@latest |
いろいろ聞かれますので順に答えていきます。
2.static(静的ブロック)かdynamic(ダイナミックブロック)を選択
1 2 3 |
? The template variant to use for this block: (Use arrow keys) > static dynamic |
ダイナミックブロックは動的に内容を取得して出力内容を変えるものです。
(最新記事一覧のように動的にデータを取得して出力するものや、HTML・CSS・JSの変更がすぐ反映されるブロック)
3.ブロックのスラッグを入力(フォルダ名にもなります)
1 |
? The block slug used for identification (also the output folder name): (example-static) |
4.namespaceを入力
1 |
? The internal namespace for the block name (something unique for your products): (create-block) |
namespaceはプラグインの名前になります。
ブロック名がnamespace/block-nameとなります。
5.ブロックの表示名を入力
1 |
? The display title for your block: (Example Static) |
6.ブロックの説明を入力(任意)
1 |
? The short description for your block (optional): (Example block scaffolded with Create Block tool.) |
7.ブロックのアイコン名を入力(任意 未入力だとsmileyになる)
1 |
? The dashicon to make it easier to identify your block (optional): (smiley) |
このウィザード中ではDashiconsから選択するしかできないが、後ほど自作アイコンを使用することもできます。
8.ブロックの分類を選択
1 |
? The category name to help users browse and discover your block: (Use arrow keys) |
記事編集時のブロック選択画面で自作ブロックがどのカテゴリに属するかを選択します。
9.プラグインとして開発するなら「y」、ブロックのみの雛形を生成するなら「N」を選択します。
1 |
? Do you want to customize the WordPress plugin? (y/N) |
「N」を選択するケースは、1つのプラグインの中に複数のブロックを含める際に使用するオプションです。
10.プラグインの解説ページのURLを入力。
配布しないプラグインなら未入力でいいと思います。(任意)
1 |
? The home page of the plugin (optional). Unique URL outside of WordPress.org: |
11.プラグインのバージョンを入力。
未入力だと「0.1.0」になります。
1 |
? The current version number of the plugin: (0.1.0) |
12.プラグイン作者の名前を入力(任意)
1 |
? The name of the plugin author (optional). Multiple authors may be listed using commas: (The WordPress Contributors) |
13.プラグインのライセンスを入力(任意)
1 |
? The short name of the plugin’s license (optional): (GPL-2.0-or-later) |
14.プラグインのライセンスの説明ページを入力(任意)
1 |
? A link to the full text of the license (optional): (https://www.gnu.org/licenses/gpl-2.0.html) |
15.ブロックを多言語対応する際のテキストドメインを指定します(任意)
1 |
? A custom domain path for the translations (optional): |
ブロックの多言語対応は翻訳ファイルを用意し、load_plugin_textdomain
という関数でこのテキストドメインと翻訳ファイルを読み込みます。
多言語対応を行わないのであれば未入力で構いません。
16.ブロックのバージョンアップを行った際の通知先URLを指定します(任意)
1 |
? A custom update URI for the plugin (optional): |
ここでURLを指定しておくとブロックの更新を通知することができますが、配布しないブロック/プラグインであれば未入力で構いません。
ここまで入力すれば3で入力した名前でフォルダが作成され、その中に必要ファイルが生成されます。
このフォルダをまるごとpluginsフォルダ内にコピーするとプラグインとして表示されます。
このプラグインを有効化すれば記事編集画面でブロックとして使用することができます。
@wordpress/create-block
でできあがるブロックは初期状態では
サンプルブロック – hello from the saved content!
と固定文言が表示されるだけのものです。
生成されたフォルダの中身は以下のようになっています。
1 2 3 4 5 6 7 8 9 |
.editorconfig .gitignore block-sample.php(3で指定した名称がファイル名になる) package-lock.json package.json readme.txt ├─node_modules ├─build └─src |
基本的に手を加えるのはsrcフォルダの中身のみです。
srcの中身は以下の通りです。
1 2 3 4 5 6 7 8 9 |
└─src block.json edit.js editor.scss index.js save.js(静的ブロックのみ) render.php(ダイナミックブロックのみ) style.scss view.js |
ブロックの名前やバージョンなどの定義ファイルです。@wordpress/create-blockで入力した内容を元に生成されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "name": "block-sample/block-sample", "version": "0.1.0", "title": "サンプルブロック", "category": "text", "icon": "smiley", "description": "Example block scaffolded with Create Block tool.", "example": {}, "supports": { "html": false }, "textdomain": "block-sample", "editorScript": "file:./index.js", "editorStyle": "file:./index.css", "style": "file:./style-index.css", "render": "file:./render.php",(ダイナミックブロック時のみ) "viewScript": "file:./view.js" } |
Webサイトと管理画面どちらでも呼ばれるCSSです。
管理画面でのみ呼ばれるCSSです。
ブロックの登録を行うJSです。ここからsave.js/render.php、edit.js、view.jsが呼ばれます。
save
関数の返り値がWebサイト上での出力結果になります。
Webサイトでの表示時の処理を書くファイルです。
ダイナミックブロックにおけるWebサイト上での出力結果です。
静的ブロックのsave.jsと同等のものです。
Edit
関数の返り値がエディタ上での表示になります。
エディタ上での処理を書くファイルです。
Webサイト上で任意の(かつ固定の)Javascriptを実行したいときはview.jsファイル内で呼び出します。
Google Analyticsや広告用のJSなどを使用するときに使うものです。
src配下のそれぞれのファイルを修正してもそのままでは修正は反映されません。
ビルドを実行してブロック用ファイルを生成する必要があります。
ターミナルで以下のコマンドを実行します。
1 |
npm run build |
また、ファイルの変更を監視して変更があれば随時ビルドするコマンドもあります。
(他の環境ではwatchと呼ばれることが多い)
1 |
npm run start |
それでは実際にオリジナルのブロックを作成してみます。
今回は最親階層のカテゴリーを取得し、そのカテゴリー配下の最新記事5件を取得して表示するようなダイナミックブロックを作ってみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
カテゴリーA ├最新記事1 ├最新記事2 ├最新記事3 ├最新記事4 ├最新記事5 カテゴリーB ├最新記事1 ├最新記事2 ├最新記事3 ├最新記事4 ├最新記事5 .... |
こんな感じで表示されるものを作ります。
ダイナミックブロックの場合、render.php内ではWordPressの関数が一通り使用できます。
カテゴリーを取得してforeach、そしてそのカテゴリーIDをクエリとしてget_postsで記事を取得すればいいだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<div <?php echo get_block_wrapper_attributes(); ?>> <?php $cats = get_categories([ 'hide_empty'=>false ]); foreach($cats as $cat){ if($cat->parent === 0){ $catName = $cat->name; echo '<h3>'.$catName . '</h3>'; $catId = $cat->term_id; $catPosts = get_posts([ 'category' => $catId, 'numberposts' => 5 ]); if(count($catPosts)){ echo '<ul>'; foreach($catPosts as $catPost){ echo '<li><a href="' . get_permalink($catPost) . '">'; echo $catPost->post_title; echo '</a></li>'; } echo '</ul>'; } } } ?> </div> |
これだけでとりあえずカテゴリーとそれぞれのカテゴリーに所属する最新記事5件を表示するブロックができました。
テスト記事が少ないから5件出てませんが…。
ただ、これで終わりにするのはさすがに簡単すぎるのでサイドバーで記事取得数を設定できるようにしたいと思います。
まずは記事取得件数として使用する変数を定義します。
block.jsonにattributes
という項目を追加し、変数名と型、デフォルト値を入力します。
1 2 3 4 5 6 7 8 |
...略 "attributes": { "articleCount": { "type": "number", "default": 5 } } ...略 |
次にサイドバーに設定項目を表示させるため、Edit
の返り値にInspectorControls
というタグを含めます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import {__} from '@wordpress/i18n'; //InspectorControlsを使えるように追加 import {useBlockProps, InspectorControls} from '@wordpress/block-editor'; //PanelBodyがサイドバーの中身。追加で今回はドロップダウンで選択できるようにしたいのでSelectControlを追加 import {PanelBody, SelectControl} from '@wordpress/components'; import './editor.scss'; export default function Edit(props) { //属性の取得と保存用の関数を呼び出す const {attributes, setAttributes} = props; return ( <p {...useBlockProps()}> <InspectorControls> <PanelBody title={'取得記事数'}> <SelectControl label="記事数を選択" value={attributes.articleCount} options={[ {value: 1, label: '1'}, {value: 2, label: '2'}, {value: 3, label: '3'}, {value: 4, label: '4'}, {value: 5, label: '5'} ]} onChange={(newValue) => { //<select>のvalueはstringになってしまうので型変換しておく setAttributes({articleCount: Number(newValue)}); }} /> </PanelBody> </InspectorControls> {__( 'カテゴリーと最新記事', 'category-and-recent' )} </p> ); } |
これでサイドバーにドロップダウンのオプション項目を追加することができました。
ドロップダウン以外でもラジオボタンやテキストが利用できますので詳しくはこちらを参照してください。
上記で保存したオプション項目(articleCount)を出力時に呼び出して記事取得件数として使用します。
block.jsonで定義した変数は$attributes
というグローバル変数に入ります。
1 2 3 4 |
$catPosts = get_posts([ 'category' => $catId, 'numberposts' => $attributes['articleCount'] ]); |
これで表示記事数のカスタマイズができるカテゴリー+記事一覧ブロックができあがりました。
これだけで十分だと個人的には思いますが、エディタ上での表示が出力時そのままを反映していないので少々不細工です。
ダイナミックブロックにはServerSideRender
という、出力時の表示をエディタ上でも再現する機能があるのでそれを組み込んでみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
//ServerSideRenderを使うためにインポート import ServerSideRender from '@wordpress/server-side-render'; ...略... //editの返り値にServerSideRenderタグを追加 return ( <p {...useBlockProps()}> <InspectorControls> <PanelBody title={'取得記事数'}> <SelectControl label="記事数を選択" value={attributes.articleCount} options={[ {value: 1, label: '1'}, {value: 2, label: '2'}, {value: 3, label: '3'}, {value: 4, label: '4'}, {value: 5, label: '5'} ]} onChange={(newValue) => { setAttributes({articleCount: Number(newValue)}); }} /> </PanelBody> </InspectorControls> <ServerSideRender block="wrblock/category-and-recent"//ブロック名 attributes={{ articleCount: attributes.articleCount//渡したいキーと値 }} /> </p> ); |
これでエディタ上でも出力時と同様の表示が実現できました。
ドロップダウンで取得記事数を変更することですぐに再描画もされます。
ということで今回はブロック作成の基本を調べつつカテゴリーや記事を取得して表示するダイナミックブロックを作ってみました。
実際に手を動かしたことでなんとなくフルサイト編集対応テーマについても分かってきたような、まだまだ全然意味不明なような…という感じですが、引き続きやっていきたいと思います。
ADs
vjvokh
e8ouem
dvdbs6