WordPress ショートコードの作成方法 - 電子書籍を無料公開

まえがき

本書は、WordPressユーザーのためのPHP入門を読んだ方が、一歩進んだ使い方として、ショートコードを作成するためのガイドです。
この電子書籍は、エムディーエヌコーポレーションより発刊されている「WordPressユーザーのためのPHP入門 はじめから、ていねいに。」を読了された方を想定して、同書籍よりも少し進んだカスタマイズ方法を紹介しています。
本書では、WordPressの便利な機能であるショートコードを題材に取り上げます。ショートコードの例には、「会社の住所を表記する」ショートコードなど、簡単ではありますが実用性のあるコードを採用しています。
また、実用例として、プラグイン「Shortcode for My Mitsu Estimation Form」で使用されているショートコードをベースにしたコードも紹介しています。このプラグインは、自動計算&見積書発行ウェブサービス「マイ見積」をWordPressに埋め込み、ホームページ上で見積フォーム=>項目選択=>見積書発行ができるようになります。

WordPressのカスタマイズ

WordPressでは、様々なカスタマイズを行うことができます。かんたんな例を挙げると、

  • 投稿本文の後に、同じ著者の記事を表示する
  • 投稿の公開日が古い場合、「情報が古くなっている可能性があります。」と表示する
  • 「続きを読む」の後に、広告リンクを追加する
などです。テーマにPHPコードを書き込んだり、プラグインを導入したりすることで、様々なカスタマイズができます。このようなカスタマイズをする場合は、テーマ・プラグインのファイルにPHPコードを書き込みます。
では、もし、記事本文中に、PHPコードを書いたらどうなるでしょうか。試しに書いてみると分かりますが、PHPコードがそのままテキストとして表示されます。PHPで書いたプログラムが実行されるわけではありません。
では、記事中でプログラムを実行したい場合は、どうすれば良いでしょうか。記事の先頭、あるいは末尾でプログラムを実行したいのであれば、テーマファイルで記述しておく、という方法もあります。しかし、この方法は記事の途中だったら使えませんね。心配はいりません。このような時に役立つのがショートコードです。

ショートコードとは

WordPressでは、記事の中でプログラムを実行したい、といった場合に、プログラムを呼び出すことができます。この仕組みのことをショートコードと呼びます。また記事に挿入するコードのことをショートコードと呼ぶこともあります。記事中に、

[gallery]

のように、[ ] (角括弧) で囲ったコードを記述すると、プログラムを実行できます。[gallery]のgalleryの部分で、実行するプログラム名を指定します。関数名みたいなもの、と考えてもらえばよいでしょう。
[gallery]は、WordPress本体に用意されているショートコードで、投稿に添付された画像を一覧表示するHTMLを出力します。食べ歩きブログなどで、料理の写真をずらっと見せたい、というような場合に役立ちます。試しにご自身のブログに記述してみましょう。

上の画像のように、投稿の画像を大きさをそろえて並べて表示してくれます。

ショートコードはどんなときに使う?

ショートコードの使い方、もちろんいろいろありますが、簡単な例から紹介していきたいと思います。

定型文を表示したい場合

定型文を表示したい場合、ショートコードが便利です。たとえば、会社の住所などです。記事の中に

468-0076 愛知県名古屋市天白区八事石坂129-507

と書けば良いのではないか、と思うかもしれませんね。もし、会社がずっと移転しないのであれば、直接記事の中に書いておけば良いかもしれません。しかし、将来、会社の規模が大きくなった場合に移転するかもしれません。そのような場合、記事の中に住所を直接書いていたらどうなるでしょうか。記事の中一箇所なら修正も楽ですが、もし複数あったら、記事の数だけ書き換えなければなりません。
一方、ショートコードにしておけば、会社移転時に一箇所変えれば対応できます。 コードは下記のようになります。詳しくは後ほど説明します。

function companyaddress_function( $atts, $content = NULL ) {
     return “468-0076 愛知県名古屋市天白区八事石坂129-507”;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

そして、投稿編集画面で、

[companyaddress]

と入力します。投稿を保存して、実際のページを見ると、

468-0076 愛知県名古屋市天白区八事石坂129-507

のように表示されます。
会社が移転した場合に、会社概要のページ、投稿内に住所を記述したページ、、、を全て探して変更するのは大変ですね。しかし、ショートコードにしておけば、一箇所の変更だけで済ますことができます。

function companyaddress_function( $atts, $content = NULL ) {
     return “460-0008 愛知県名古屋市中区栄2-2-1 名古屋広小路伏見中駒ビル5F”;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

とすれば、住所を一括で更新できますね。

定型文を指定した時間に変更したい場合

さて、会社移転が2017年7月1日だったとしましょう。もちろん、移転日に書き換えすればよいわけです。しかし、移転日に、ウェブサイトの情報更新の時間を取れればよいですが、実際には、移転日には他の作業に追われて書き換えできないかもしれません。
そのような場合でも、ショートコードで住所を記述しておけば、非常に楽になります。ここでは、書き換える日付をショートコード内に指定しておく方法を紹介します。実際の移転日に書き換えなくてもよくなります。
PHPでは、日付を取得することができました。日付を取得する関数はdate()でしたね。date()関数では、日付のフォーマットを指定できます。たとえば、

date('Y年m月d日');

とすれば、2017年05月17日のように、年4桁月2桁日2桁の形式で日付を表示します。もし、

 date('Ymd');

とすれば、20170517のように表示します。このdate()関数を使うと、日付により表示を変えることができます。
条件によって表示を変えるには、ifを使います。(ifについて忘れてしまった方は、「WordPressユーザーのためのPHP入門」でおさらいしましょう。)

if ( date(‘Ymd’) >= 20170701 ) {
    return ‘新しい住所’;
    } else {
    return ‘現在の住所’;
    }

とすれば、2017年7月1日以降は新しい住所、2017年6月30日までは現在の住所、と、日付に応じて変更できます。
ショートコードにすると下記のような形になります。

function companyaddress_function( $atts, $content = NULL ) {
     if ( date(‘Ymd’) >= 20170701 ) {
      return ‘新しい住所’;
     } else {
      return ‘現在の住所’;
     }
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

運用上は、まずは

function companyaddress_function( $atts, $content = NULL ) {
     return ‘現在の住所’;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

と書いておき、会社を移転する場合は、ショートコードを定義する関数companyaddress_functionの中身を書き換えて日付に応じて変更するようにする、となるでしょう。

投稿内で動的な処理をしたい場合

さて、会社の住所をショートコードを使って表示する方法を紹介しました。しかし、決まった内容の表示であれば、(ショートコードを使わないと管理の手間はかかりますが、)ショートコードは必須ではありませんでした。 では、投稿本文中で動的な処理をしたい場合はどうでしょうか。
単純な例として、リンクURLから、iframeを作成してみます。

function my_iframe_function( $atts, $content = NULL ) {
     $format = '<iframe src="%s" width="640" height="480"></iframe>';
     return sprintf( $format,
      esc_url( $content )
     );
    }
    add_shortcode( 'myiframe', 'my_iframe_function' );

投稿画面では、

[myiframe]https://my-mitsu.jp/estimation/274[/myiframe]

のように記述します。そうすると、
<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe> のように表示します。URLを入力すると、iframeタグで出力してくれれば、貼り付け作業が楽になりますし、HTMLタグの打ち間違いもなくなります。「HTMLタグを打ち間違えて正しく表示されない」といった失敗が減らせます。

ちなみに上のURLは、顧客を待たせずにホームページで見積書を発行するサービス「マイ見積」の自動見積フォームを埋め込みしています。マイ見積を使うと、下のように、項目から選ぶだけで自動計算してくれ、ホームページ上で見積書PDFが発行できます。

ショートコードの作り方

では、実際にショートコードを作成していきましょう。まずは一番簡単な、定型文表示のショートコードからみていきましょう。定型文を表示したい場合で紹介したコードです。

function companyaddress_function( $atts, $content = NULL ) {
     return “468-0076 愛知県名古屋市天白区八事石坂129-507”;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

上のコードは、2つの部品に分けられます。関数を定義している部分と、関数をショートコードとして登録する部分です。 まずは、関数を定義している部分をみてみましょう。

function companyaddress_function( $atts, $content = NULL ) {
     return “468-0076 愛知県名古屋市天白区八事石坂129-507”;
    }

関数の定義の仕方は、WordPressで使う関数を定義するときとほぼ同じです。

function 関数名(引数) { …ここに実際のコード… }

という形です。ショートコードを作るときに注意する点は、2つあります。

  1. 引数: $atts, $content と決まっている
  2. 関数の出力: return する (echo や print ではない)
ショートコードを書くときに、オプションを設定できます。引数の部分は、オプションを受け取るために必要な機能です。ここは後の節で説明します。定型文表示するショートコードのように、オプション設定なしの場合は、引数は( $atts, $content = NULL ) と書いておけばよいです。
もうひとつの注意点は、 return する、という点です。定型文を出力したいからショートコードを書くので、echo を使いたくなるかもしれませんね。しかし、ショートコードの決まりで return を使うので、間違えないようにしましょう。
つづいて、関数をショートコードとして登録する部分のコードです。

add_shortcode( 'companyaddress', 'companyaddress_function' );

add_shortcodeは、WordPressに用意されている関数です。引数に、ショートコードで呼び出すときの名前、呼び出される関数名、を設定します。上の例では、ショートコードで呼び出すときの名前が companyaddress で、呼び出される関数名が companyaddress_function です。
投稿の中で、 [companyaddress] と記述すれば companyaddress_function が実行されます。 定型文の場合のショートコードをまとめると、下記のようになります。

function 関数名( $atts, $content = NULL ) { // 関数の引数は、この通り記述する
     return “ここに、表示したい文やhtmlを記述する”; // return することに注意する
    }
    add_shortcode( 'ショートコード名', '関数名' ); // 関数名は、定義した関数の名前。// ショートコード名は、投稿で呼び出す名前。

使うシーンとしては、会社の住所を指定したり、商標名を指定したり、といったところでしょうか。商標名であれば、 最初は「マイ見積(商標出願中)」としておき、承認されたら、「マイ見積(商標登録第○○号)」に書き換える、といった使い方になるでしょう。

名前は被らないようにする

ショートコードで呼び出すときの名前は、他と被らないように命名してください。上の例ではcompanyaddressにしていましたが、もし、テーマ・プラグインで同じ名前のショートコードが作成されていた場合、期待通りに動かなくなります。このような事態を避けるために、名前が被らないように注意して命名する必要があります。
では、どのような名前をつければ良いでしょうか。companyaddressという名前は、このショートコードの役割を表しています。逆に言えば、ショートコードの役割が同じか、または似ているものがテーマ・プラグインで定義されている場合、名前も同じになる可能性があります。
名前が被るのを避けるための名前の付け方として良くあるのは、自分で独自の接頭辞を付ける方法です。mdn_companyaddressのように命名します。companyaddressが仮に被ったとしても、自分独自の接頭辞mdnは、まず被ることはありません。こうすることで、テーマ・プラグインで定義されているショートコードと偶然同じ名前になる可能性をほぼゼロにできます。

ショートコードを登録する

ショートコードは、add_shortcodeで登録できることが分かりました。では、add_shortcodeは、どこに書けばよいでしょうか。主な方法として、以下の2つがあります。

  1. 独自プラグインを作って、プラグイン中に書く
  2. テーマのfunctions.phpに書く
1. 独自プラグインを作って、プラグイン中に書く、という方法が王道です。wp-content/pluginsフォルダ内にショートコードを登録するphpファイルを置きます。プラグインとして認識されるには、単にフォルダ内に置くだけでは不十分です。ファイルの冒頭に、決まったコメントを書く必要があります。コメントの例を以下に示します。

<?php
    /*
    Plugin Name: プラグインの名前
    */
    (以下省略)

もし、プラグイン名が、「My CompanyAddress Plugin」の場合は、以下のように記述します。

<?php
    /*
    Plugin Name: My CompanyAddress Plugin
    */
    (以下省略)

ファイルの1行目の<?phpは、phpコードの開始を示します。必ず記述するようにします。 この他にも、様々な項目がありますが、最低限必要なのは、このPlugin Nameですので、必ず書くようにしましょう。 ファイル全体は下記のようになります。

<?php
    /*
    Plugin Name: My CompanyAddress Plugin
    */

    function companyaddress_function( $atts, $content = NULL ) {
     return “468-0076 愛知県名古屋市天白区八事石坂129-507”;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

プラグインをアップロードしたら、WordPress管理画面からプラグインを有効にしてください。
2. テーマのfunctions.phpに書く、という方法は、実装が比較的楽、というメリットがあります。プラグインにする場合は、WordPressが決めたルールをファイルの冒頭に書かなければいけませんが、この方法の場合は、functions.phpに書くだけで有効になります。

function companyaddress_function( $atts, $content = NULL ) {
     return “468-0076 愛知県名古屋市天白区八事石坂129-507”;
    }
    add_shortcode( 'companyaddress', 'companyaddress_function' );

の部分を、テーマのfunctions.phpに書けば、有効になります。
この方法のデメリットとしては、テーマを切り替えた場合にショートコードが無効になる、という点があげられます。新しいテーマでも同じショートコードを使いたい場合、新しいテーマのfunctions.phpにもコードを書く必要があります。また、公開されているテーマをベースにしている場合は、子テーマを作っておかないと、元のテーマのアップデートで自分の変更が失われるので注意が必要です。
なお、公式ディレクトリにテーマ登録する場合に、テーマと直接関係ないショートコードをfunctions.phpに書くと修正を要請されるようです。

ショートコードにデータを渡す

定型文をショートコードで表示することができました。もちろん、定型文を表示するショートコードも十分役立ちます。しかし、ショートコードのメリットはそれだけではありません。ショートコードをもっと自由に使う方法が用意されています。ショートコードに渡すデータを指定することで、様々な表示が可能になります。この節では、ショートコードにデータを渡す方法を説明します。

URLを渡して、iframeタグをする例

ショートコードにデータを渡す例として、URLを渡して、iframeタグをする例を紹介します。WordPressの投稿画面のエディタでは、リンク(aタグ)を挿入するボタンは用意されていますが、iframeを挿入するボタンは用意されていません。ショートコードでiframeを出力できると便利ですね。
以下のようなショートコードを書くと、iframeを出力できます。

function my_iframe_function( $atts, $content = NULL ) {
     $format = '<iframe src="%s" width="640" height="480"></iframe>';
     return sprintf( $format,
      esc_url( $content )
     );
    }
    add_shortcode( 'myiframe', 'my_iframe_function' );

投稿画面では、

[myiframe]https://my-mitsu.jp/estimation/274[/myiframe]

のように記述します。そうすると、

<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe>

が出力されます。
ではコードの解説です。投稿画面で、[ショートコード名]データ...[/ショートコード名]と書いたとき、データ...がショートコードで実行する関数の第二引数 $content に渡されます。上の例では、 https://my-mitsu.jp/estimation/274が $content に渡されます。

URL → iframeタグへ変換する処理

$format = '<iframe src="%s" width="640" height="480"></iframe>';
    return sprintf( $format,
     esc_url( $content )
    );

の部分は、$content に投稿画面で入力したURLが格納されています。これを、

  1. esc_url
  2. sprintf
  3. return
の順で処理しています。
esc_urlは、URLとして許可される文字だけになるように、余計な文字を削除またはエンコードする関数です。WordPressに用意されている関数です。今回のように、URLを出力する場合は、必ずこの関数で処理してから出力します。もし、esc_urlでの処理を怠ると、「意図しないコードを実行してしまう」などのセキュリティ上好ましくない問題が発生することがあります。
sprintfは、文字列の中に文字列を当てはめて返す関数です。PHPに用意されている関数です。第一引数に文字列を取ります。第一引数の文字列の中に、第二引数を当てはめます。当てはめる箇所は、第一引数の文字列内に、特殊な意味を持つ文字列%sで指定します。sprintfで処理すると、%sの部分に第二引数の文字列を当てはめた文字列が作られます。
上の例では、第一引数が<iframe src="%s" width="640" height="480"></iframe>、第二引数がhttps://my-mitsu.jp/estimation/274 なので、作られる文字列は<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe>です。
最後に、sprintfで作られた文字列をreturnします。これでショートコードの処理の完了です。

ショートコードの属性

さて、ショートコードでiframeを出力することができました。しかし、前節のショートコードは、iframeの幅と高さが固定値でした。常に同じ大きさでiframe埋め込みしたい場合は良いかもしれません。しかし、埋め込むページが変われば、埋め込みの幅や大きさを変えたい場合もあると思います。そういった時には、どうすればよいでしょうか。
このようなとき、ショートコードでは、属性を設定できる仕組みがあります。
今回は、まず、投稿画面での書き方を見てみましょう。投稿画面では、

[myiframe width=”640” height=”480”]https://my-mitsu.jp/estimation/274[/myiframe]

のように記述して、属性を設定します。[myiframe width=”640” height=”480”]の width=”640” height=”480” 部分が属性です。
ではここで、もう一度、myiframe ショートコードを出力するphpをみてみましょう。

function my_iframe_function( $atts, $content = NULL ) {
     $format = '<iframe src="%s" width="640" height="480"></iframe>';
     return sprintf( $format,
      esc_url( $content )
     );
    }

第一引数に $atts がありますね。ここが属性を受け取る部分です。$atts には、投稿画面でショートコードに属性として設定したものが連想配列で格納されています。
上の例でいえば、$atts の中身は、

array(
     'width' => 640,
     'height' => 480
    );

となっています。属性を活用するには、関数 my_iframe_function を書き換えます。

function my_iframe_function( $atts, $content = NULL ) {
     $format = '<iframe src="%s" width="%d" height="%d"></iframe>';
     return sprintf( $format,
      esc_url( $content ),
      intval( $atts['width'] ),
      intval( $atts['height'] )
     );
    }

のようにします。$atts['width']、$atts['height']は、属性で設定した値が格納されています。これらをsprintfを使用して、iframeの書式に当てはめれば完成です。
この例でもsprintfを使用しています。今回は、複数の箇所に一気に当てはめています。
sprintf では、当てはめる文字の場所を%sで指定できます。%sのほかに%dも、似たような働きをします。%sと%dの異なる点は、当てはめるものが、

%s … 文字
%d … 数字

という違いがあります。URLは文字(数字も含む)なので%s、widthとheightは数字なので%d、と使い分けます。
当てはめる箇所が複数ある場合、第二引数以降を順に当てはめていきます。今回は%sが1つ、%dが2つと、合計3つあるので、

第二引数 => 一個目の%s or %d
第三引数 => 二個目の%s or %d
第四引数 => 三個目の%s or %d

となります。
出力結果は、

<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe>

になります。
intvalは、phpに用意されている関数で、受け取った変数を数値(整数)に変換します。$atts['width']や$atts['height']に、数値以外の文字が入っていた場合に除去してくれます。

文字列連結とsprintf

sprintfを使う代わりに、’<iframe src="’ . esc_url( $content ) . ’" width="640" height="480"></iframe>’のように文字列連結で生成することもできます。この方法は、短い文字列なら良いのですが、文字列が長くなると読みにくくなります。
もし、widthやheightも文字列連結する場合、’<iframe src="’ . esc_url( $content ) . ’" width="' . intval( $atts['width'] ) . '" height="' . intval( $atts['height'] ) . '"></iframe>’となります。
もちろん、自分一人でプログラミングするなら、どちらでも良い、俺は文字列連結のほうが良い、という意見も成立するかもしれません。しかし、複数人でプログラミングする場合は、コーディング規約を決めることが多いです。このため、文字列連結でもsprintfでも書けるようにしておくと良いでしょう。

ショートコードの属性のデフォルト値

このコードで、ショートコードの属性が受け取れるようになりました。

function my_iframe_function( $atts, $content = NULL ) {
     $format = '<iframe src="%s" width="%d" height="%d"></iframe>';
     return sprintf( $format,
      esc_url( $content ),
      intval( $atts['width'] ),
      intval( $atts['height'] )
     );
    }

では、これで完全でしょうか。実は、上のコードは問題があります。何が問題になるのか、考えてみましょう。
ショートコードでは、属性を指定できました。投稿画面で、widthやheightが指定できるわけです。属性は便利ではありますが、投稿画面で必ず入力されるとは限りません。もし、

[myiframe]https://my-mitsu.jp/estimation/274[/myiframe]

のように、widthやheightを未指定のショートコードを記入された場合、

<iframe src="https://my-mitsu.jp/estimation/274" width="0" height="0"></iframe>

と、widthとheightの値が0になります。(0になるのは、intvalが数値に変換するからです。)
「自分一人でブログ書いているから、自分さえ気をつければ良い」という意見もあるかもしれませんが、プログラミングでは、ユーザーが気をつけることに依存したコードは好ましくありません。
プログラム側で対処することは比較的簡単です。属性が指定されなかった場合にはデフォルト値を使用する、という仕組みにしておけば良いです。
WordPressでは、デフォルト値を設定するときに便利な関数shortcode_attsが用意されています。
-------------------------------------------------------------------
shortcode_atts( $pairs, $atts, $shortcode);
$pairsは連想配列で、ショートコードの属性(連想配列のキー)とデフォルト値(連想配列の値)で構成されます。
$attsは連想配列で、ショートコードで指定された属性(連想配列のキー)とその値(連想配列の値)です。ショートコードの処理を書く関数(上の例のmy_iframe_function)の第一引数を渡せばOKです。
$shortcodeは、フィルターフックに付ける名前です。指定しなくても良いですが、指定することが推奨されています。ここは次章で解説します。
-------------------------------------------------------------------

$default_atts = array(
     'width' => 640,
     'height' => 480
    );
    $atts = shortcode_atts( $default_atts, $atts );

このようにshortcode_attsを使うと、

widthが指定されていればその値を使用し、指定されていなければ640
heightが指定されていればその値を使用し、指定されていなければ480

となります。

[myiframe]https://my-mitsu.jp/estimation/274[/myiframe]

のように、widthとheightが未指定の場合でも、デフォルト値が使用されるので、

<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe>

となります。また、もし、[myiframe length=”200” … ] のように、想定していない属性(この例ではlength)が指定されていた場合、shortcode_attsが除去してくれます。

-------------------------------------------------------------------
完成したコード

function my_iframe_function( $atts, $content = NULL ) {
     $default_atts = array(
      'width' => 640,
      'height' => 480
     );
     $atts = shortcode_atts( $default_atts, $atts );
     $format = '<iframe src="%s" width="%d" height="%d"></iframe>';
     return sprintf( $format,
      esc_url( $content ),
      intval( $atts['width'] ),
      intval( $atts['height'] )
     );
    }
    add_shortcode( 'myiframe', 'my_iframe_function' );

-------------------------------------------------------------------

使い方の例1:属性の指定無し

[myiframe]https://my-mitsu.jp/estimation/274[/myiframe]

例1の出力(width, height はデフォルト値になる)

<iframe src="https://my-mitsu.jp/estimation/274" width="640" height="480"></iframe>

使い方の例2:属性の指定あり

[myiframe width=”800” height=”600”]https://my-mitsu.jp/estimation/274[/myiframe]

例2の出力

<iframe src="https://my-mitsu.jp/estimation/274" width="800" height="600"></iframe>

フィルターフック

前章では、ショートコードの作り方を見てきました。デフォルト値も設定しておけば、使いやすくなるでしょう。 この章では、WordPressに用意されているフィルターフックを使い、ショートコードをさらに柔軟にカスタマイズできるようにします。

一般的なフィルターフック

WordPressでは、フィルターフックを設定することができます。フィルターフックは、値を加工することができます。

function my_iframe_function( $atts, $content = NULL ) {
     $default_atts = array(
      'width' => 640,
      'height' => 480
     );
     $atts = shortcode_atts( $default_atts, $atts );
     $format = '<iframe src="%s" width="%d" height="%d"></iframe>';
     return sprintf( $format,
      esc_url( $content ),
      intval( $atts['width'] ),
      intval( $atts['height'] )
     );
    }
    add_shortcode( 'myiframe', 'my_iframe_function' );

の太字部分を

$default_width = apply_filters( 'myiframe_width', 640 );
    $default_height = apply_filters( 'myiframe_height', 480 );
    $default_atts = array(
     'width' => $default_width,
     'height' => $default_height
    );

としてみます。

function my_iframe_function( $atts, $content = NULL ) {
     $default_width = apply_filters( 'myiframe_width', 640 );
     $default_height = apply_filters( 'myiframe_height', 480 );
     $default_atts = array(
      'width' => $default_width,
      'height' => $default_height
     );
     $atts = shortcode_atts( $default_atts, $atts );
     $format = '<iframe src="%s" width="%d" height="%d"></iframe>';
     return sprintf( $format,
      esc_url( $content ),
      intval( $atts['width'] ),
      intval( $atts['height'] )
     );
    }
    add_shortcode( 'myiframe', 'my_iframe_function' );

こうすると、myiframe_widthフック、myiframe_heightフックに、処理する関数を追加して、この値を変更することができます。以下の例をみてみましょう。

function smaller( $value ) {
     return intval( $value * 0.75 );
    }
    add_filter( 'myiframe_width', 'smaller' );
    add_filter( 'myiframe_height', 'smaller' );

この例は、サイズを0.75倍したい、という場合です。0.75倍する関数smallerを定義しています。この関数を、myiframe_widthフック、myiframe_heightフックに追加すると、幅も高さも0.75倍になる、というわけです。
もし、サイズを1.25倍したいのであれば、以下のようになります。

function bigger( $value ) {
     return intval( $value * 1.25 );
    }
    add_filter( 'myiframe_width', 'bigger' );
    add_filter( 'myiframe_height', 'bigger' );

このように、フィルターフックを設定しておくと、値の変更を柔軟に行うことができます。

ショートコードの属性用のフィルターフック

apply_filtersは、WordPressのどこでも使えるフィルターフックで、汎用性が高いものでした。ショートコードの場合は、WordPressの一般的なフィルターフックの他に、ショートコードの属性用のフィルターフックを設定できます。
ショートコードの属性用のフィルターフックは、前章でも出てきたshortcode_attsで設定できます。前章の例では省略していた第三引数を指定すると、フックが有効になります。

$default_atts = array(
     'width' => 640,
     'height' => 480
    );
    $atts = shortcode_atts( $default_atts, $atts, 'myiframe' );

shortcode_atts関数では、第三引数が指定されている場合、apply_filtersを使って、shortcode_atts_指定した名前 というフックを有効にします。上の例では、shortcode_atts_myiframeというフックが有効になります。

function adapt_height( $atts ) {
     $atts['height'] = 360;
    }
    add_filter( 'shortcode_atts_myiframe', 'adapt_height' );

のように記述すると、高さを360に変更できます。
ショートコードの属性値に限定されますが、shortcode_atts関数の引数でフィルターフック名を指定するだけで有効になるのは楽ですね。
※shortcode_atts関数の引数のフィルターフックは、ユーザーが入力した属性値とデフォルト値の確認作業後に実行されるフックです。my_iframe_function関数の myiframe_width、 myiframe_heightは、デフォルト値にかかるフックです。似たような働きをしますが、フック処理の場所が異なることに注意してください。

古いショートコードに注意しよう

WordPressは、後方互換性を重視したプロダクトです。ショートコードが導入されたWordPress2.5から、2017年5月時点の最新版のWordPress4.7.5に、アップデート可能になっています。しかし、WordPressの開発が進むにつれて、新しく追加されたもの、非推奨になったもの、には注意しなければなりません。

shortcode_attsの第3引数

shortcode_attsの第3引数は、本編でも述べたように、ショートコードにフィルターフックを楽に追加できる機能です。またWordPress本体でフィルターフックを追加する箇所を用意してくれているおかげで、他の人が作成したプラグイン・テーマのショートコードに、フィルターフックが用意されていることが期待でき、カスタマイズしやすいです。
shortcode_atts関数は、WordPress2.5からあります。ショートコードが導入された時ですね。しかしWordPress2.5の時点では、第3引数はありませんでした。WordPress3.6以降から、shortcode_attsの第3引数が指定可能になりました。このため、古いプラグイン・テーマの場合には、フィルターフックが用意されていないことがあります。
もし、そのようなプラグイン・テーマを見つけた場合は、作者にフィードバックすると、改善される可能性が高いです。

extract関数

PHPには、extract関数が用意されています。extract関数は、配列を引数にとります。その配列をバラして、別々の変数にする働きをします。 言葉だけだと分かりにくいので、実際のコードで見てみましょう。

$atts = array( 'width' => 640, 'height' => 480);
    extract( $atts );
    echo $width; // 640
    echo $height; // 480

となります。extractで処理しない場合は、$atts['width']、$atts['height']と記述するところを、extractを使うと$width, $heightと記述できます。
一見するとextractは便利そうな機能ですが、エディタで自動補完されないことが多い、など、デメリットもあります。このため、現在のWordPressのコーディング規約では、extractは使わないことになっています。
古いプラグイン・テーマでは、extractを使っているものがあるかもしれないので、注意しましょう。
良くないコードの例(この例は、shortcode_attsの第3引数が無い&extractを使う、という二重に良くない例です。)

extract( shortcode_atts( array(
      'prop_a' => 'aaa',
      'prop_b' => 'bbb',
    ), $atts ) );

著者 水野 史土
2013年にレスキューワーク株式会社設立。中小企業をITで支援するシステムを構築・運営している。2016年9月に自動見積計算サービス「マイ見積」が中部経済新聞で紹介される。
WordPressのwpdb::prepareメソッドのセキュリティチェック実装および警告メッセージを改善した実績により「PHP5セキュリティウィザード2015」に認定される。
著書
■ WordPressユーザーのためのPHP入門 はじめから、ていねいに。[第2版]
■ 徹底攻略 PHP5 技術者認定 [上級] 試験問題集 [PJ0-200]対応

発行 レスキューワーク株式会社