ショートコード内でget_template_part()を使う場合は工夫が必要!
2018/04/22
STINGER5をカスタマイズしていた時のこと。
記事中にGoogle AdSenseの広告を手軽に入れられるようにしようと、ソースコードを修正していると。
あれ、うまく動かない!?
簡単な修正だから、サクッと2~3分で終わるかな、なんて高をくくっていた、はるる。
甘かったです。
やりたかったこと
はるるがやりたかったのは、こんな実装。
ショートコードを使い、広告出力コードを記事中に出力する
記事中に[adsense]と記載すると、あらかじめ指定しておいた、Google AdSenseの広告出力コードをHTMLに出力する。(本当は半角の[]ですが、そうするとここにも広告が出力されてしまうので、先の例は全角の[]を使用。)
実際に出力させてみると、このような感じ。
通常の記事ページでしか出力しない
たとえば固定ページなどで、誤って[adsense]と記載しても、広告出力コードをHTMLに出力しない。
もし誤って記載した場合は、長さゼロの文字列を出力する。
広告出力コードは、テンプレートファイルに記載の内容を出力する
広告出力コードは、テンプレートファイル(ad-template.php)に記載し、その内容を出力する。
これは本来はベタ書き(下記ソースコード3行目に、広告出力コードをベタで書き込む)でも構いません。
ですがこういったものをベタ書きするのは、はるるの好みではありません。
というのは、Google AdSenseの広告出力コードは、今後張り替える可能性があるから。
その際のソースの修正ミスによるトラブルを未然に防ぎたい、というわけ。
テンプレートファイルに広告出力コードを外出しすれば、テンプレートファイル(ad-template.php)の修正のみで、広告出力コードの変更が可能になります。
そのため修正の際のミスは、ほとんど起こり得ないはず。
そこで、はるるが最初に試したソースコードがこちら。
1 2 3 4 5 6 7 8 | function showads() { if(is_single()){ return get_template_part('ad-template'); }else{ return ''; } } add_shortcode('adsense', 'showads'); |
これをテーマフォルダ内のfunctions.php、あるいは子テーマのfunctions.phpに追記し、記事中で[adsense](→本当は半角の大かっこ)と記述することで、呼び出し元が個別の記事の時にかぎり、テーマフォルダ内、または子テーマフォルダ内に用意したad-template.phpに記載の内容を出力させる、という修正をしたつもり。
ですが…。
ちゃんと動かないんですよね、これ…。
実際にやってみると分かるんですが、記事の一番上に広告が表示されてしまいます…。
これでは仕様を満たせていませんし、使い物になりませんね。
というわけで少し調べてみると、すぐに原因が判明。
こうすれば、ちゃんと動きます!
修正した、仕様通りに動くコードがこちら!
1 2 3 4 5 6 7 8 9 10 | function showads() { if(is_single()){ ob_start(); get_template_part('ad-template'); return ob_get_clean(); }else{ return ''; } } add_shortcode('adsense', 'showads'); |
修正は、ob_startメソッドやob_get_cleanメソッドを利用するように変更した、という軽微な内容。
これだけで、先の仕様を満たした動作を行うようになります。
当初のコードが仕様通りに動かなかった理由
なぜ当初のコードが仕様通りに動かなかったのか、というと、WordPressのソースのgeneral-template.phpにある、get_template_partメソッドの実装やtemplate.php内にあるlocate_template、load_templateメソッドの実装を見れば、分かります。
つまるところ、内部でrequireメソッドを呼んでいるため、出力内容のバッファリングを行わないと、直ちに出力が実行されてしまうんです。
そのためob_startメソッドやob_get_cleanメソッドを利用した、出力バッファリングを行うことで改善した、というわけ。
気付きにくいけれど
この問題はPHPの実行時エラーが出るわけではなく、出力位置がずれてしまう(想定よりも先に)だけであるため、原因に気付きにくいです。
はるるは普段、あまりPHPを触ることがないので、ソースを確認するまでは、原因の検討がつかず、結構ハマりました。
こういうのは日頃から、PHPを使っている方であれば、すぐに多分出力バッファリングが原因だ!
となるのかもしれませんね。
WordPressでブログを運営していく以上、PHPも程々には勉強しなきゃ、なんて思いました。
それでは今回はこの辺で。