is_preview()

is_preview()は、プレビュー画面かどうかで条件分岐ができるタグです。

使いどころとしては、query_posts() を使用してループをカスタマイズした際、「下書き」状態の記事がプレビューできない件を解消するなど。

query_posts() はデフォルトでは「公開」状態の記事しか表示しませんので、下書き中の記事は公開しないとプレビュー不能という状態に陥ります。

is_preview()

 

引数「post_status=draft」を入れてやることで「下書き」も表示することができますが…。
これだとプレビューではない通常の閲覧時にも「下書き」が見えてしまうというトンデモナイ状況に。

こういったときに、is_preview() をつかって条件分岐してやるとうまくいきます。

 

is_preview()2

便利ですね!

コード記述例

<?php //プレビューのときだけ下書きも表示
if(is_preview()):
query_posts('cat=1&post_status=draft,publish');
else:
query_posts('cat=1');
endif; ?>
<?php if (have_posts()):while (have_posts()):the_post(); ?>
〜 略 〜
<?php endwhile; else: ?>
<p>只今、投稿はありません。</p>
<?php endif; ?>
<?php wp_reset_query(); ?>

HTMLエディタで、自動整形の影響を最小限に抑えるには

管理画面の本文エリアで、HTMLエディタでコーディングをしたとき。
保存したとたんにタグがとんだりして困ったことはありませんか?

  • id属性が消えてしまい、cssで設定していた背景画像がきえたり、アンカーリンクが動かない
  • 全角スペースで体裁を整えていたが、スペースが消えてしまった
  • コメントアウトが表示されてしまった
  • <img>のrel属性が消え、javascriptが動かない
  • <iframe>が消えた…
  • 改行が消えた…

などなど…。

WordPressのエディタには自動整形機能があります。 なので、この自動整形機能によってタグが意図しない状態になることがあるのです。

そして、さらに。

ユーザーの権限によって、この自動整形機能に差があることに最近気がつきました。
例えば、「特権管理者」で編集した記事「編集者」が編集すると、特定の属性・タグが消える…といったようなことです。
(通常の範囲内の操作と思いますので、ほとんどバグでは!?と個人的には思います)

幸い、自動整形対策のプラグインや関数は公開されていますので有り難く使わせていただき、自動整形を一番良い形で防ぐのはどのやりかたが良いか?検証をしてみました。

★とても長いので、お急ぎの方はこちらへどうぞ。
★この記事は2012年時点のものです。2016年版はこちらへどうぞ。

検証環境

  • WordPress:ver.3.4.2
  • OS:Mac OSX 10.7.5
  • 使用ブラウザ:FireFox 15.0.1

使用プラグイン・関数

TinyMCE Advanced →詳細へ

ver.3.4.9
言わずと知れたビジュアルエディタを使い易くするプラグイン。
今回は、このプラグインの「Stop removing the <p> and <br /> tags when saving and show them in the HTML editor」という機能だけを使います。

PS Disable Autoformatting →詳細へ

ver.1.0.8
自動整形&タグ除去回避プラグイン。
今回は最終的にこちらを採用させていただきました。感謝感謝です。

Unfiltered MU →詳細へ

ver.1.3.1
権限による差異をなくしてくれるプラグイン。
Automattic製です。もうだいぶん古いプラグインですが、ちゃんと動きます。
願わくばプラグインじゃなくてWordPress本体に手をいれてほしいところ。

属性値消失を防ぐ関数 →参考サイト様

※参考サイト様のソースにrel属性を追加しています。

<?php
if ( !function_exists('pnd_allow_all_attr') ) {
function pnd_allow_all_attr ($init) {
$ext_elements = '';

$target_elements = array(
'a', 'b', 'base', 'big', 'blockquote', 'body', 'br', 'caption', 'clear', 'dd', 'div', 'dl',
'dt', 'em', 'embed', 'font', 'form', 'h', 'head',  'hr', 'html', 'i', 'img', 'input',
'li', 'link', 'meta', 'nobr', 'noembed', 'object', 'ol', 'option', 'p', 'pre', 'rel','s',
'script', 'select', 'small',  'span', 'strike', 'strong', 'sub', 'sup', 'table',
'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'tt', 'u', 'ul',
'iframe'
);
$target_attr = array(
'*'
);

foreach ($target_elements as $target_element) {
$ext_elements .= ",".$target_element."[".implode('|',$target_attr)."]";
}

if ( !empty($ext_elements) ) {
if ( !empty($init['extended_valid_elements']) )
$init['extended_valid_elements'] .= $ext_elements;
else
$init['extended_valid_elements'] = trim($ext_elements, ',');
}

return $init;
}
add_filter( 'tiny_mce_before_init', 'pnd_allow_all_attr', 100 );
}
?>

検証手順

  1. HTMLエディタに検証コードを流し込む
  2. ビジュアルエディタに切り替えて更新
  3. プレビューし、ソースを表示させたものを検証

検証項目

  1. 全プラグイン停止(これをデフォルトとする)
  2. TinyMCE(Stop removing the <p> and <br /> tags when saving and show them in the HTML editorにチェック)
  3. Unfiltered MU
  4. PS Disable Autoformatting

※上記に関して「特権管理者」「管理者」「編集者」「投稿者」それぞれで検証手順にそって検証コードを編集しソースを取得。

検証コード

<h1>自動整形検証コード</h1>

<h2>pタグ</h2>
<p>pタグが消えないかどうか</p>

<h2>行頭一字空け</h2>
<p> 行頭一字空けを全角アキで確保できるか</p>

<h2>改行タグ</h2>
<p>XHTMLの改行タグ<br />が消えないかどうか</p>
<p>HTML5の改行タグ<br>が消えないかどうか</p>

<h2>連続改行</h2>
<p>XHTMLの改行タグによる<br /><br /><br />3連続改行</p>

<h2>空タグ</h2>
<p id="test_id02"></p>
<div id="test_id01"></div>

<h2>id属性とclass属性</h2>
<div id="test_id">
<p>id属性とclass属性が消えないかどうか</p>
</div>

<h2>rel属性</h2>
<img src="example.jp" rel="example" alt="example" />

<h2>clear属性</h2>
<br clear="all">

<h2>ul中にclear属性</h2>
<ul>
<li>あいうえお</li>
<li>かきくけこ</li>
<br clear="all">
</ul>

<h2>スタイル直書き</h2>
<p style="margin-top:30px;padding-bottom:20px;">直書きしたスタイル属性が消えないかどうか</p>

<h2>コメントアウト</h2>
<p>段落中の<!--コメントアウト-->が消えないかどうか</p>
<!--段落外のコメントアウトが消えないかどうか-->

<h2>テーブル</h2>
<table>
<tr>
<th style="width: 120px;" scope="row">テキスト</th>
<td>テキストテキスト</td>
</tr>
</table>

<h2>imgタグ</h2>
<img src="example.jp" alt="example" />

<h2>iframe</h2>
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.co.jp/maps?f=q&amp;amp;source=s_q&amp;amp;hl=ja&amp;amp;geocode=&amp;amp;q=%E6%9C%AD%E5%B9%8C%E9%A7%85&amp;amp;aq=&amp;amp;sll=43.437574,142.851354&amp;amp;sspn=4.155917,7.734375&amp;amp;brcurrent=3,0x5f0b29a33b13e82f:0xb96643d25f25d813,0&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=%E6%9C%AD%E5%B9%8C%E9%A7%85%EF%BC%88%E5%8C%97%E6%B5%B7%E9%81%93%EF%BC%89&amp;amp;t=m&amp;amp;z=14&amp;amp;ll=43.068625,141.350801&amp;amp;output=embed">インラインフレーム非対応ブラウザへのメッセージ</iframe><br /><small><a href="http://maps.google.co.jp/maps?f=q&amp;amp;source=embed&amp;amp;hl=ja&amp;amp;geocode=&amp;amp;q=%E6%9C%AD%E5%B9%8C%E9%A7%85&amp;amp;aq=&amp;amp;sll=43.437574,142.851354&amp;amp;sspn=4.155917,7.734375&amp;amp;brcurrent=3,0x5f0b29a33b13e82f:0xb96643d25f25d813,0&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=%E6%9C%AD%E5%B9%8C%E9%A7%85%EF%BC%88%E5%8C%97%E6%B5%B7%E9%81%93%EF%BC%89&amp;amp;t=m&amp;amp;z=14&amp;amp;ll=43.068625,141.350801" style="color:#0000FF;text-align:left">大きな地図で見る</a></small>

<h2>HTML5のタグ</h2>
<section>セクション</section>
<nav>ナビゲーション</nav>
<article>アーティクル</article>
<aside>アサイド</aside>
<header>ヘッダー</header>
<footer>フッター</footer>
<address>アドレス</address>

[検証結果] デフォルト

特権管理者

pタグ 消えない ※HTMLエディタでは非表示
行頭一字空け × 不可
改行タグ 消えない ※HTMLエディタでは非表示※XHTMLタグに置き換わる
連続改行 × 不可
空タグ(p) × 消失
空タグ(div) 消えない
id属性 消えない
class属性 消えない
rel属性 × 消失
clear属性 × 消失 brタグはpタグに代わり、&nbsp;をはさんだ状態
clear属性(ul内) × 消失ほか brタグは消失、ulタグがさらにulタグで囲まれ、最下行にp空タグ出現
スタイル直書き 消えない
スタイル直書き
(th内)
消えない
コメントアウト
(タグ外)
× 見える ※pタグで囲まれるため、コメントアウトが表示されてしまう
コメントアウト
(タグ内)
OK
テーブル 消えない ※<tbody>を強制的に入れられる
iframeタグ 消えない ※pタグで囲まれる※iframeタグが空タグにされる ※widthやstyleなどの属性値の位置が変わる
HTML5タグ 消えない
imgタグ 消えない ※消えないが<p>タグに囲まれてしまう

管理者・編集者・投稿者

特権管理者との差分のみ表記。

id属性 × 消失
スタイル直書き
(th内)
× 消失
iframe × 消失 ※iframeタグが消失

 

[検証結果] TinyMCE Advanced

特権管理者

pタグ 消えない ※HTMLエディタでは非表示
行頭一字空け 可能
改行タグ 消えない ※HTMLエディタで表示される※XHTMLタグに置き換わる
連続改行 × 不可
空タグ(p) 消えない ※半角スペースが挿入され、空タグではなくなる
空タグ(div) 消えない ※半角スペースが挿入され、空タグではなくなる
id属性 消えない
class属性 消えない
rel属性 × 消失
clear属性 × 消失 ※brタグはpタグに代わり、&nbsp;をはさんだ状態
スタイル直書き 消えない
スタイル直書き
(th内)
消えない
コメントアウト
(タグ外)
× 見える ※pタグで囲まれるため、コメントアウトが表示されてしまう
コメントアウト
(タグ内)
OK
テーブル 消えない ※<tbody>を強制的に入れられる
iframeタグ 若干問題あり ※pタグで囲まれる※iframeタグが空タグにされる ※widthやstyleなどの属性値の位置が変わる
HTML5タグ 消えない
imgタグ 消えない ※消えないが<p>タグに囲まれてしまう

管理者・編集者・投稿者

特権管理者との差分のみ表記。

id属性 × 消失
スタイル直書き × 消失 ※pタグは消えないが、thタグでは消失
スタイル直書き
(th内)
× 消失
iframe × 消失 ※iframeタグが消失

 

[検証結果] Unfiltered MU

特権管理者・管理者・編集者

デフォルト[特権管理者]と同じ結果

投稿者

id属性 × 消失 ※id属性が消失
スタイル直書き
(th内)
× 消失
iframe × 消失 ※iframeタグが消失

 

[検証結果] PS Disable Autoformatting

特権管理者

pタグ 消えない
行頭一字空け 可能
改行タグ 消えない ※HTMLエディタでは非表示※XHTMLタグに置き換わる
連続改行 可能
空タグ(p) 消えない
空タグ(div) 消えない
id属性 消えない
class属性 消えない
rel属性 × 消失
clear属性 × 消失 ※brタグはpタグに代わり、&nbsp;をはさんだ状態
スタイル直書き 消えない
スタイル直書き
(th内)
消えない
コメントアウト
(タグ外)
OK
コメントアウト
(タグ内)
OK
テーブル 消えない ※<tbody>を強制的に入れられる
iframeタグ 若干問題あり ※pタグで囲まれる※iframeタグが空タグにされる ※widthやstyleなどの属性値の位置が変わる
HTML5タグ 消えない ※ソース上の改行がなくなる
imgタグ 消えない ※消えないが<p>タグに囲まれてしまう

管理者・編集者・投稿者

id属性 × 消失
スタイル直書き
(th内)
× 消失
iframe × 消失 ※先頭に改行が入り、かつiframeタグが消失

…以上の検証結果から、自動整形防止に関するプラグインは「PS Disable Autoformatting」を採用。
決め手は「連続改行」「タグ外コメントアウト」が使用可能だったこと。
連続改行は文法違反ですが(改行タグは体裁をととのえるためのものではない)、コーディングの現場ではどうしても使われてしまいます。。。

そして、権限による差異をなくすべく「Unfiltered MU」も同時採用。
さらにfunctions.phpには「属性値消失を防ぐ関数」を追記しておきます。
これで同様に検証すると…。
ちなみに権限は「編集者」です。

 

[検証結果] PS Disable Autoformatting + Unfiltered MU + 属性値消失を防ぐ関数

pタグ 消えない
行頭一字空け 可能
改行タグ 消えない ※XHTMLタグに置き換わる
連続改行 可能
空タグ(p) 消えない
空タグ(div) 消えない
id属性 消えない
class属性 消えない
rel属性 消えない
clear属性 × 消失 ※brタグはpタグに代わり、&nbsp;をはさんだ状態
スタイル直書き 消えない
スタイル直書き
(th内)
消えない
コメントアウト
(タグ外)
OK NG ※場合によってOKな場合もあるが、<p>で囲まれる場合もあり法則不明。
コメントアウト
(タグ内)
OK
テーブル 消えない ※<tbody>を強制的に入れられる
iframeタグ 若干問題あり ※pタグで囲まれる※iframeタグが空タグにされる ※widthやstyleなどの属性値の位置が変わる
HTML5タグ 消えない ※ソース上の改行がなくなる
imgタグ 消えない ※消えないが<p>タグに囲まれてしまう

 

かなりいい感じになりました。
しかし、ここまでしてもいくつか実現不可能なものがありますね。
注意が必要な部分は残ります。
特に、消えたタグの残骸(?)がソースのしたのほうに突如出現して、ソースを汚す現象も確認されました。
ということで、以下まとめです。

 

【まとめ】HTMLエディタで、自動整形の影響を最小限に抑えるには

  • プラグイン「PS Disable Autoformatting 」+「 Unfiltered MU 」を使用
  • 「属性値消失を防ぐ関数」をfunctions.phpに追記(今回はrel属性について確認をしました)
  • コーディング済みソースを編集する権限で「投稿者」は使わない
  • <br clear=”all”>など、廃止属性の使用禁止
  • 文法違反に注意(<ul>〜</ul>の中に<li>以外をいれる等)
  • <iframe>は「空タグになること」「<p>で囲まれてしまうこと」を念頭においておく
  • <img>は「<p>で囲まれてしまうこと」を念頭においておく
  • <table>は<tbody>が入ることを念頭においておく
  • コメントアウトは使わない [11月6日追記]

こんな感じでしょうか。
…それにしても、権限によって自動整形の挙動が違うこと、本当に驚きました。
結構知られていることなのでしょうか??皆さん困っていないのでしょうか…。
それとも、コーディング済みのソースを流し込むことが一般的ではないのでしょうか。
(個人的には嫌いですが)

長い間、おかしいおかしいと思っていたこと、まとめることは出来てちょっとスッキリしました。

 

よし!法則つかんだぞ!と思ったのもつかの間、検証では大丈夫だったコメントアウトにNGパターンが発生してしまいました。どうやら使わない方が安全のようです。
自動整形は本当に手強いです。私は、管理画面内にコーディング済みのソースを流し込んだあとは必ず目視確認をしているのですが、今回はそれで救われました。コメントアウトがおかしくなった影響で、その部分以下がごっそり抜け落ちるという現象になっていたので、気付かずにリリースしていたら危ないところでした…。また気付いたことがあればアップしたいと思います。 [11月6日追記]

 

関連記事

esc_html()

HTMLタグをエスケープしてくれます。
例えば、HTML文の中に<br>と書いた場合、改行が行われるだけで<br>というタグ自体はユーザ画面には表示されません。

esc_html()を使えば「<」は「&lt;」、「>」は「&gt;」へと置き換えられ、<br>というタグをユーザ画面で表示できます。

記述例

<br>をエスケープし、表示させる。

<?php echo esc_html('<br />'); ?>

home_url()

現在のブログのホームURLを返します。
よくにたタグに、get_home_url()があります。

引数

  • path…ホームURLからの相対パス。
  • scheme…URLスキーム。現在利用できるのは ‘http’ と ‘https’。

コード記述例

現在のブログのホームURLを表示
例)http://example.ne.jp

<?php echo home_url(); ?>

 

現在のブログのホームURL直下に「/abc」を追加しURLスキームを「https」に変更。
例)https://example.ne.jp/abc

<?php echo home_url('/abc','https'); ?>

フロントページの表示あれこれ

表示設定にある「フロントページの表示」、これがどうも解りづらいので調べてみました。

最新の投稿

これを選択すると、自動的にフロントページのループに投稿が表示されるようになります。

  • 適応されるテンプレート:front-page.php ない場合は home.php
  • 適応される条件分岐タグ:is_front_page(),is_home()
  • URL:/(サイトのルート)

固定ページ

これを選択すると、任意の固定ページをフロントページとして表示させることが出来ます。

「フロントページ」だけを設定

任意の固定ページがフロントページとして表示されるようになります。ループには固定ページの内容が表示されます。

  • 適応されるテンプレート:front-page.php ない場合は page.php
  • 適応される条件分岐タグ:is_front_page()
  • URL:/(サイトのルート)

front-page.phpを置かなければpage.php(カスタムテンプレートもOK)が適応されるため、ホームを複数用意しておいて表示設定で簡単切り替え…ということも出来るわけです。

 

「投稿ページ」だけを設定

任意の固定ページがフロントページとして表示されるようになります。ループには投稿の内容が表示されます。

  • 適応されるテンプレート:home.php ない場合は index.php
  • 適応される条件分岐タグ:is_home()
  • URL:/(サイトのルート)と /example(任意のスラッグ)

…この「投稿ページ」という設定項目が実に謎でした。
せっかくの固定ページなのに、設定したとたんにテンプレートがhome.phpまたはindex,phpになってしまいます。ループに表示されるのも投稿ですし、「最新の投稿」を選ぶのと変わらないのでは?と思っていたのですが、次のような違いがあることがわかりました。

【表示される投稿に依存せずにスラッグを決められる】
たとえば「hoge」というカテゴリのアーカイブを表示させたとしても、その固定ページのスラッグが「example」ならURLは「/example」となります。(まあ、固定ページなので当たり前といえば当たり前ですが…)
その場合、サイトのフロントページと同じページがもう1つ存在する状況となります。…この状況が活用される場面はあるのでしょうか。「フロントページ」を同時設定したほうがスマートかもしれません。

【wp_list_pages()でURLを吐き出せる】
グローバルナビのひとつとして「お知らせ」とか「ブログ」を出したい、しかもwp_list_pages()で自動吐き出しにしたい!というときに実現できます。これも、「フロントページ」を同時設定したほうがスマートでしょう。

 

雑感

ぶっちゃけ「固定ページ」の「投稿ページ」設定は個人的には必要ないです(笑)
wp_list_pages()でURLを吐き出せるのは少し魅力ですが、実際の作業ではハードコードすることが多いので、あまり必要ないかな…。

 

テンプレートと条件分岐タグ対応表
最新の投稿 固定ページ
フロントページ 投稿ページ
テンプレート front-page.php front-page.php home.php
条件分岐タグ is_front_page(), is_home() is_front_page() is_home()

get_page_uri()

固定ページのスラッグを取得します。

例えば企業サイトなどで、ページ毎にイメージ画像を変えたいとき、今まで私はif文による条件分岐でハードコードしてました。これが地味に時間を食うのです。。。

例)

<h2>
<?php // この会社について
if(is_page('about')): ?>
<img src="img/about.jpg">
<?php // 製品について
elseif(is_page('product')): ?>
<img src="img/product.jpg">
<?php // お問い合わせ
elseif(is_page('contact')): ?>
<img src="img/contact.jpg">
・
・
・
<?php
endif; ?>
</h2>

この面倒くさいif文が、下記のように1行ですんでしまいます。
画像名にページスラッグを規則的に使っている場合に限定されますが。
(というか是非そのような画像名にしましょう)

 

<h2><img src="img/<?php echo get_page_uri($post->ID);?>.jpg"></h2>

 

コードは必要最小限に書くことが、解りやすさ・速さにつながるんだなーと痛感します。

is_home()とis_front_page()の違いって何?

ずっと謎だったので検証してみました。
「表示設定」で「フロントページの表示」をどう設定しているかによって
is_home()が機能したり、is_front_page()が機能したり、また両方機能したりします。
結果は…

is_front_page()とis_home()の両方機能

is_front_page()が機能

固定ページ>フロントページ

is_home()が機能

固定ページ>投稿ページ

 

is_home()の存在理由となっているのがこの「固定ページ」の「投稿ページ」です。何ですかこれは…。

どうやら「ブログのトップページ」ということらしいのですが、非常に理解しづらかったです。フォーラムでも熱いやりとりが交わされています

私の場合、「ブログのトップページ」は、ブログとして使うカテゴリのアーカイブページを利用するので、個人的にはいらない機能です。唯一、意味があるとすればwp_list_pages()で「ブログのトップページ」が吐き出せることでしょうか。

謎は残りますが、is_home()とis_front_page()がそれぞれどういうときに機能するのかがわかり、一応すっきりしました。

なんだか気になったのでさらに検証してみました。

関連記事

マルチブログでの条件分岐

親ブログかどうかの条件分岐タグはありますが、それだけだと不便です。
子ブログのときも、それぞれに条件分岐させたいときがあります。そんなときは、ブログIDで条件分岐させてしまいましょう。

コード記述例

<?php // ブログIDを取得し$blog_idに代入
global $current_blog;
$blog_id = $current_blog->blog_id;
// ブログIDが1のとき
if ($blog_id == 1){ ?>
<!-- ID1のブログに出したい内容 -->
<?php // ブログIDが2のとき
} else if ($blog_id == 2){ ?>
<!-- ID2のブログに出したい内容 -->
<?php } ?>

ちなみにブログIDの調べ方は、ダッシュボード上部の黒帯左側にある「参加サイト」→「サイトネットワーク管理者」→「サイト」で、「パス」にマウスオーバーすると画面下部にパスとidが表示されるので解ります。(ver.3.3.2、Macの場合)

get_the_category()

記事のカテゴリー情報を配列で返します。

※参考にさせてい頂いたサイト様:WordPress私的マニュアル

 

位置

ループ内・外

引数

なし

変数

カテゴリーID cat_ID
カテゴリー名 cat_name
カテゴリースラッグ category_nicename
カテゴリー説明文 category_description
親カテゴリーID。ない場合「0」 category_parent
カテゴリーに属する記事数 category_count

※カテゴリーに関する部分のみ抜粋

コード記述例

カテゴリ名を表示

<?php // カテゴリ名を表示
$cat = get_the_category();
$cat = $cat[0];
echo $cat->cat_name;
?>