ショートケーキでも食いながらショートコードを作ってみよー

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
そういやショートケーキってもう何年も食べてないな

この記事を三行にまとめると

本文の中に直接phpの処理を書きたい場合があるかもしれない
ショートコードを自作するのが良いでしょう
上に15(イチゴ)があるってことでショートケーキの日なんだって
Wordpressで記事を作成する際、本文の中に直接phpの処理を書きたい場合があるかもしれない。

例えばphpのdate()を使って記事の本文中に現在日時を表示したいとする。でも下記のように書いても上手く動きません。

//投稿した本文
<?php echo date('Y-m-d H:i:s') ?>

本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

//実際の表示


本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

こんな風にphpの部分がブランクになってしまいます。

phpを記述できるようになるプラグインもあるにはあるのですが、セキュリティの面などを考慮すると推奨できるものではないみたいです。

じゃあそういう時にはどうすれば良いかってーと、Wordpressにはショートコードという機能が用意されています。なので「どうしてもここにphpの処理が必要だな〜」って時にはショートコードを自作するのが良いでしょう。

やり方は簡単です。でもいろんなパターンを見ていこうと思うのでちょっと長くなります。ショートケーキでも食べて適度に糖分補給しながら見てくださいな☆



ショートコードの基本的な書き方

説明は後に回してとりあえず現在日時を表示するためのショートコードを実際に書いてみます。

//functions.php
function sample_function() {
  echo date('Y-m-d H:i:s');
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
[sample_shortcode]

本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

//実際の表示
2017-07-22 12:12:12

本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

まずfunctions.phpに「add_shortcode()」というショートコードを追加するための関数を記述します。第一引数はタグ名、第二引数は関数名です。上記の場合だと「sample_shortcode」がタグ名で、「sample_function」が関数名です。

sample_function()の中には現在日時を表示するコードが入ってますね。これでショートコードを使う準備ができました。

ショートコードを記事本文の中で使う場合は[]を使います。角かっこって言うんでしたっけ?

[タグ名]

タグ名にはマルチバイト文字も使えます。

//functions.php
function sample_function() {
  echo date('Y-m-d H:i:s');
}
add_shortcode('サンプル', 'sample_function');

//記事本文
[サンプル]

本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

あまりやることはないかもしれませんが、俺はどうしてもタグ名に奥さんの名前を使いたいんだみたいな場合は、[ジェニファー]とか試してみると良いでしょう。まあジェニファーだったらアルファベットで良いと思うが。

ショートコードが存在しない場合はエラーにはならずに、[タグ名]がそのまま表示されます。



本文の途中に表示したい

上記の例では本文の一番上にショートコードを書いて表示しました。ではこれを文章の真ん中に持ってきたらどうなるでしょうか。

//functions.php
function sample_function() {
  echo date('Y-m-d H:i:s');
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
本文です本文です本文です。

[sample_shortcode]

本文です本文です本文です。
本文です本文です本文です。

意図としては二行目に現在日時が出てほしいわけですが、残念ながらこの書き方だと意図通りにはなりません。先ほどと同じように現在日時が本文の一番上に表示されます。

//望んだ表示
本文です本文です本文です。

2017-07-10 12:12:12

本文です本文です本文です。
本文です本文です本文です。

//実際の表示
2017-07-10 12:12:12

本文です本文です本文です。

本文です本文です本文です。
本文です本文です本文です。

これは関数の中でechoを使って表示しているからです。

Wordpressの処理としては、データベースから本文を取得した後、画面に表示する前に本文にショートコードが含まれているか判定し、あればその時点で実行します。つまり本文を表示する前にsample_function()が実行されて、echoで本文より上に表示されてしまうという感じです。

だからこういう場合はechoではなくreturnで値を返すだけにしておくのが良いでしょう。

//functions.php
function sample_function() {
  //echoをreturnに変える
  return date('Y-m-d H:i:s');
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
本文です本文です本文です。

[sample_shortcode]

本文です本文です本文です。
本文です本文です本文です。



値を渡す

sample_function()に値を渡したい場合。例えば現在の一日後や一ヶ月後の日時を表示できるようにdate()に値を渡してみます。

//functions.php
function sample_function($atts) {
  return date('Y-m-d H:i:s', strtotime($atts[0]));
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
本文です本文です本文です。

[sample_shortcode +1days]
[sample_shortcode +1month]

本文です本文です本文です。
本文です本文です本文です。

タグ名の後ろに半角スペースを入れて関数に渡したい値を書きます。コーテーションはつけない。つけても良いですが、その場合はダブルコーテーションじゃないと上手く動かないです。シングルはダメ。

//値が取れる
[sample_shortcode "+1days"]

//値が取れない
[sample_shortcode '+1month']

値は配列で入ってくるので、一つだけ値を渡したら「$atts[0]」で受けとることになります。

複数の値を渡す場合はスペースでどんどん追加する。

//functions.php
function sample_function($atts) {
  print_r($atts);
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
[sample_shortcode aaa bbb ccc]

//実際の表示
array([0] => aaa [1] => bbb [2] => ccc)

こんな感じですね。



配列のキーを指定する

上記のような書き方だと$attsで受け取る配列のキーは数値になります。このキーを任意の文字列にしたい場合。

//functions.php
function sample_function($atts) {
  print_r($atts);
}
add_shortcode('sample_shortcode', 'sample_function');

//投稿した本文
[sample_shortcode a=aaa b=bbb c=ccc]

//実際の表示
array([a] => aaa [b] => bbb [c] => ccc)

htmlタグの属性を書くような感じで「キー名=値」と書くことで任意のキー名にできます。この場合はコーテーションはあってもなくても、シングルでもダブルでも正常に動くっぽいです。

//どのパターンも問題ない
[sample_shortcode a=aaa b='bbb' c="ccc"]



ファイルを読み込む場合

先ほどのechoと似たようなパターンになってしまうものとして、requireやincludeを使ってファイルを読み込む場合があります。

//functions.php
function sample_function() {
  require 'datetime.php';
}
add_shortcode('sample_shortcode', 'sample_function');

//datetime.php
<?php echo date('Y-m-d H:i:s') ?>

//投稿した本文
本文です本文です本文です。

[sample_shortcode]

本文です本文です本文です。
本文です本文です本文です。

例えばこんな感じで「datetime.php」というファイルを作って、それを本文の途中に読み込むみたいな。これもさっきと同様の理屈で本文が表示される前にrequireが実行されるので、本文より上に現在日時が表示されてしまいます。

こういう時は「ob_start()」で出力バッファを有効にすると良いと思います。

//functions.php
function sample_function() {
  ob_start();
  require 'datetime.php';
  return ob_get_clean();
}
add_shortcode('sample_shortcode', 'sample_function');

//datetime.php
<?php echo date('Y-m-d H:i:s') ?>

//投稿した本文
本文です本文です本文です。

[sample_shortcode]

本文です本文です本文です。
本文です本文です本文です。

ベストなやり方かは僕にも分かりませんが、これなら本文の途中にファイルを読み込ませることが可能です。数行のphp処理を書く程度ならともかく、javascriptなども一緒に書く場合はこうやってファイルに書いてrequireするのが良いんじゃないでしょうか。本文にscriptタグを書くのもあまりよろしくないからね。



カスタムフィールドでショートコードを使う

今までは記事本文の中にショートコードを書いてきました。ではカスタムフィールドの中でもショートコードを書けば同じように機能するのかってーと、残念ながらそうは問屋が卸さない。

カスタムフィールド

例えばこんな風に「shortcode」というカスタムフィールドを作成して、「get_post_meta()」で取得してもショートコードは実行されない。

じゃあカスタムフィールドにショートコードを書いた場合にはどうするか。

$meta = get_post_meta($post->ID, 'shortcode', true);
echo apply_filters('the_content', $meta);

まずカスタムフィールドを値を取得して「apply_filters()」という関数でショートコードを有効にしています。

僕もちゃんとは理解してないんですが、たぶんショートコードの処理は「the_content()」の中で行なっているので、apply_filtersよってカスタムフィールドの内容を本文表示のフックで行うとか……何かそんな感じ? 何言ってるか分からねーって人は、とりあえずapply_filtersを使えば行けるぞってとこだけ読み取ってください。






ふいー、こんなとこですかねー。これだけ押さえとけば基本的な使い方は問題ないと思います。

ところで今日は7月22日なんですけど、毎月22日はショートケーキの日だそうですね。カレンダーで22日の上は15日なので、上に15(イチゴ)があるってことでショートケーキの日なんだって。

みなさんはショートケーキのイチゴはどのタイミングで食べる?
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください