WordPressはPHPで動いているのに、記事の中にPHPコードがあるとうまく動かない

長いな。

まぁね、干渉しちゃうんだろうねとは思うんですが、そうは言っても動いてくれよと言うのが人情ですよ。

ショートコードで解決

タイトルではうまく動かないとか書きましたが、TOPIX版ダウの犬自動計算シートが動いているということは回避策があるということです。

まるまるここにあるとおりなんですが、WordPress投稿ページにPHP利用→ショートコードを使おう! | vdeepに従って作業します。

子テーマのfunctions.phpの最後に以下のコードを追記。

<?php
// 記事内でPHPコードを実行させるためのショートコード
// 記事内での呼び出しは[myphp file='basename']
// PHPコード本体は同一ディレクトリ内のbasename.php
function short_php($params = array()) {
  extract(shortcode_atts(array(
    'file' => 'default'
  ), $params));
  ob_start();
  include(STYLESHEETPATH."/$file.php");
  return ob_get_clean();
}

add_shortcode('myphp','short_php');
?>

本体のPHPコードは(HTMLタグも含めて)子テーマのディレクトリに保存しておきます。

そしてPHPコードを呼び出したい記事の中に以下のコードを置くと、その部分がPHPコードに置き換わります。

[myphp file='basename']

functions.phpのコメントにある通り、file=”で指定するのはphpファイルのベースネーム(パスと拡張子を除いた部分)だけです。

ショートコードって何だ?

WordPressのドキュメントによると、ショートコードとは投稿記事内で使えるマクロだそうです。[と]とで囲まれた文字列がショートコード名(myphp)で、複数の属性 (file)と値(basename)を追加することができます。

投稿記事内にショートコードが見つかると、functions.phpに追記したコードの14行目にあるadd_shortcode(‘myphp’,’short_php’)に従ってコードが展開されます。

5行目から12行目で定義されているshort_php($params = array())という関数に置き換わる際に、$paramsには属性名をキーとした値が配列として渡されます。

関数の中身

今回の関数short_php()は4つのPHP命令から成っています。

WordPressのshortcode_atts()関数

最初のextract()というPHP関数の中にあるshortcode_atts()はWordPressの関数です。この関数は二つのパラメータをとります。いずれも配列です。

ひとつ目の配列array(‘file’ => ‘default’)は連想配列で、fileというキーに対してdefaultという値を持っています。

ふたつ目の配列$paramsはshort_php()関数のパラメータ$paramsそのもので、ショートコードハンドラに渡された生の配列です。今回の場合、fileというキーに対してbasenameという値を持っています。

shortcode_atts()関数はふたつ目の配列の内容をひとつ目の配列に書き込む関数ですが、同じキーがある場合には上書きをし、ふたつ目の配列にキーが存在しない場合にはひとつ目の配列の内容をデフォルト値として採用します。

もしもふたつ目の配列の中にひとつ目の配列に存在しないキーがあった場合、それは無視されます。

つまり、正しいパラメータ指定のみ受け取り、パラメータが省略された時にはデフォルト値を採用するという振る舞いをする関数です。

今回の場合、array(‘file’ => ‘default’)はarray(‘file’ => ‘basename’)に置き換えられます。

PHPのextract()関数

extract()関数は連想配列を変数に変換する関数です。連想配列のキーを変数名として、その変数に配列の値を渡します。

前記の通りshortcode_atts()関数によってarray()の内容が置き換わったextract(array(‘file’ => ‘basename’)は$file=’basename’に変換されます。

最初の命令はショートコードの属性とその値をshort_php関数の内部に取り込んだことになります。

PHPのob_start()関数

ob_start()関数は出力のバッファリングを有効にする関数です。Outoput Bufferingですかね?

出力のバッファリングが有効になると、スクリプトからの出力は全て内部バッファに保存されます。

したがって以下のinclude文で読み込まれたPHPファイルの出力がバッファに溜まってゆきます。

PHPのinclude文

include文はPHPの制御構造です。指定されたファイルを読み込んで評価します

include文に渡されているSTYLESHEETPATHは現在のテーマのパス名(今回の場合、子テーマのfunctions.phpが存在するディレクトリ)です。

“/$file.php”中の変数$fileはextract()関数で設定されたbasenameに展開されます。そして”/$file.php”の前にある.は文字列の結合演算子なので、include(/usr/local/www/junk/wp-content/themes/xeory_base-child/basename.php)というコマンドになります。

つまりbasename.phpを読み込む動作になります。

PHPのreturn文

return文もまたPHPの制御構造です。関数内で呼び出されると即座にその関数の実行を停止し、引数を関数の値として返します

今回の場合、ob_get_clean()関数の内容を返してshort_php()関数を終了します。

PHPのob_get_clean()関数

ob_get_clean()関数は現在のバッファの内容を取得し、出力バッファを削除する関数です。

つまり今回、バッファに溜め込まれたbasename.phpの実行結果を取得し、return文によってshort_php()関数の出力として表示されることになります。

こうしてバックグラウンドで処理されたPHPの結果は(HTMLを含む)プレーンテキストとして投稿記事内のショートコードと置き換わるので、WordPressを実行しているPHPコードと干渉することなく展開されるのです。…多分。