WordPress is_single()で特定ページでjsファイルを読込む方法

is_single()で必要なページだけjsやcssファイルを読み込む方法できたのですが、ハマるところがあったので分かりやすくまとめました。

function.php、 javascript.js、 style.css等は極力触りたくないので、全てのの自作jsとcssは自分のプラグインphpで読み込んでいます。  作った複数のjsファイルを全てのページに取り込むと、ページがどんどん重たくなるので、必要なページでのみ読み込みたいのですis_single()を活用しています。

結論

以下の3点で解決しました。

  1. 投稿ページはis_single()を使う
  2. 公開前はスラッグでなくidを使う
  3. フックの中で使う (ここが一番てこずった)

記述例 ‘wp_enqueue_scripts’のフック内

テストページid=[tooltips keyword=”4416″ content=”4416は公開前のページのid”]と公開しているスラッグが”how_to_use_mathjax-latex_and_list”のページでmy_test.jsを取り込んでいます。 実行タイミングは’wp_enqueue_scripts’のフックです。

function add_scripts_by_page(){
	$PAGES_MY_TEST=array(4416,
			    "how_to_use_mathjax-latex_and_list");
    if(is_single($PAGES_MY_TEST)) {
        wp_enqueue_script(
            $handle='my_php_handle',
            $src   =plugins_url() . '/my-plugin-name/my_test.js',
            $deps  =array('jquery'),
            $ver   ='0.0.0.1',
            $in_footer=true
            );
    }
}
add_action('wp_enqueue_scripts', 'add_scripts_by_page');

投稿ページはis_single()を使う

最初、is_page()を使っていたのですが、is_page()は固定ページ(post_type==’page’:ホーム、サイトマップや問合せのページ)の事で投稿ページ用ではないようです。 投稿ページはpost_typ==’post’となり、is_single()を使わなければならないようです。 is_page()の方がそれっぽいのに、これが分かるのに半日かかりました。 

公開前はスラッグでなくidを使う

殆どのサイトではスラッグとidのどちらでも良いと書いてあったので、公開前と後でプログラムが変わらないように公開前のページ指定にもスラッグを使っていました。 しかし公開前のページにスラッグを使っても反映されませんでした。 それは公開前のページには未だスラッグが使われていないのでidで指定しなければならないのです。 ここでも分かるのに半日時間がかかった。 公開前でもスラッグを使いたかった。 上のサンプルコードでは4416と”how_to_use_mathjax-latex_and_list”を配列$PAGES_MY_TESTに入れています。 4416は公開前のページのidで”how_to_use_mathjax-latex_and_list”は公開後のページのスラッグです。 idやスラッグを沢山追加していっています。

$PAGES_MY_TEST=array(4416,
		    "how_to_use_mathjax-latex_and_list");

フックの中で使う

これもあまり書かれていませんでした。 多くのサイトでis_page()やis_single()で特定ページを確認できると書いてあるだけでしたが、実際is_page()とis_single()はプラグインのメインでは動作しません。(プラグインで使い方を書いてあるサイトも見つかりませんでしたのでStackOverFlow等を参考にしてました。)

結論は、プラグインのメインではis_single()は動作していなかったのですが、フックのタイミングかショートコード埋め込みタイミングではis_single()が動作しました。 上のコード例ではadd_action(‘wp_enqueue_scripts’, ‘add_scripts_by_page’)という、’wp_enqueue_scripts’のアクションフックイベントのタイミングでfunction add_scripts_by_pageを実行するようになっています。 ’wp_enqueue_scripts’のタイミングのfunction add_scripts_by_page内ではis_single()は動作しました。 メインに直接if(is_single([tooltips keyword=”4416″ content=”4416は公開前のページのid”])){ }を書き込んでいましたが、if文内は実行されませんでした。 is_single()は特定の時しか実行されないみたいです。(公開前ページのid=4416) wordpress.orgには『”ループ内であるグローバル変数は上書きされるので、is_page()は動作しない』と書いてありました。is_single()も動作的には同じと思います。 『ループ後であればwp_reset_query()を先に実行する事』と出てたので、wp_reset_query()もメインループ内で実行しましたが動作しませんでした。 多分メインループ直書きは実行タイミングが早すぎるのでしょうね。 ここを見たらどうも’wp_enqueue_scripts’はループ前の様です。 だからwp_reset_query()してもダメだったのですね。

順番

順番はここを参考にしました。

  1. plugin_loaded — 多分このタイミングでプラグインのメインが実行されるのだと思います。
  2. init    — StackOverFlowでwp_enqueue_script出来ないと書いてました。
  3. wp_enqueue_scripts <ーーーこのタイミングがいいようです。
  4. loop_start   — これがループの開始で
  5. loop_end  — これがループの終わりですねぇ

*wp_enqueue_scriptsはタイミングのアクションフック名で、末尾に”s”の無いwp_enqueue_scriptはjsやcssのスクリプトを取り込むfucntion名です。 ちょっと分かりにくいですね。

動作したのは

add_action(‘wp_enqueue_scripts’)で実行するfunctionの中か、add_shortcode()で実行するfunctionのなかでした。 add_shortcode()内に記述すると、自動的にそのショートコードが書かれているページでしか読み込まれないのでis_single()も必要ないのですっきりしますが、将来的にそのタイミング実行しててもオッケーなのか分からないので正しい’wp_enqueue_scripts’のタイミングでis_single()を使って取込みを管理したいと思います。

主要ファイルは変更していない理由と対策

ファイル名取扱い
以下の理由で下記ファイルは一切書き換えず、自分用のファイルで作っています。
  • バージョンアップ時書き換えられて、折角作ったコードが無くなるかもしれない。
  • 何か不具合が発生した時対処できない恐怖もある。
function.php
  • 自作プラグインphpファイルで制御。
  • ショートコードにするコード等。
  • DBから読み出してhtml化。
javascript.js
  • 自作のjsファイル。
  • 自分のプラグインのディレクトリに置いています。
  • 自作プラグインphpでwp_enqueue_styleで読み込んまする。
style.css
  • 自作のcssファイル。
  • 自分のプラグインのディレクトリに置いています。
  • 自作プラグインphpでwp_enqueue_styleで読み込んでます。

編集が見づらいし管理しにくいのでカスタムcssもテスト実行時だけ使用し、最終は自作cssに統一しています。

おまけ

以下は投稿ページでどれもnullだった

  • $post;

以下は投稿ページでどれもpostと返ってきた

  • get_post_type($post); //$postがnullだったから下と同じ
  • get_post_type();
  • get_post_type(get_the_ID());

pluginの中でslug獲得はこれget_post_field()かget_post()

ID 取得

  • get_the_ID() 下書きでも公開後でもIDが返ってきた。

get_post_field

  • get_post_field($field, $post_id, $context(option))
  • 下書き中は$field=’post_status’はdraftで返ってきた。公開後はpublish。
  • 公開後は’post_name’でslugが返ってきた。 ’post_content’も返ってきた。
  • draft中は$field=’post_name'(=slug), ‘post_content’はnull だった。
  • $field=’post_type’はpostで返ってきた。
//これで表示できた。
$slug = get_post_field( 'post_content', get_the_ID() );
echo $slug;
//これも表示できた。
$mypage = get_post( get_the_ID() );
echo $mypage->post_name;

注意

‘init’ フック

早すぎて取り込めないようです。jsやcssを取り込む適切なタイミングは’wp_enqueue_scripts’のタイミングがいいようです。

wp_enqueue_scripts

enqueueとはキュー(queue=リスト)に要素を追加する事です。 wp_enqueue_scriptでは取り込む自作jsの前に取り込んでおかなければならないjsのリストをarray内に指定できます。 例えば、取り込む自作jsがjQueryを使っている場合、jquery.jsは先に取り込んでいないといけません。 jquery.jsを取り込む指定は別途必要ですが、array(‘jquery’)とするとjqueryを先に取り込んでくれます。 なのでwp_enqueue_scriptは先に取り込むリストを作り、その取り込む順番を制御して取り込んでくれるようです。 なのでenqueue_scriptsなのですね。

echo get_post(get_the_ID()); はエラーになる

  • 文字列でなくObjectの様でechoで表示しようとするとエラーとなる。
  • $myPage->post_nameとすると文字列となり表示できる。

コメント