先日リリースした、Powerful Posts Per Pageをアップデートしました。
アップデート内容は、
- カテゴリー・タグへの対応(してたつもりができていなかったものを修正)
となります。
WordPress › Powerful Posts Per Page « WordPress Plugins
バグフィックスは @Toro_Unitまでお願いします。
先日リリースした、Powerful Posts Per Pageをアップデートしました。
アップデート内容は、
となります。
WordPress › Powerful Posts Per Page « WordPress Plugins
バグフィックスは @Toro_Unitまでお願いします。
WordPressの管理画面からカスタム投稿タイプや、各タクソノミーごとの表示件数を変更できるプラグイン、Powerful Posts Per Pageをリリースしました!
WordPressの管理画面の 「設定->表示設定」から、カスタム投稿タイプやタクソノミーのアーカイブページの投稿数を指定できます。
ここで指定された値は、ロード時に、pre_get_postsを使って、WordPressのループを変更します。
もうcategory.phpやらarchive.phpにquery_postsを書いたり、WordPressのデフォルトの表示件数を1件にしてみたりそんなことする必要はありません!!!!
query_postsを捨てよ、pre_get_postsを使おう【追記あり】【報告あり】 | notnil creation weblog等で、春先当たりからpre_get_postsが大きなブームになっていますよね。
そんなこんなで、僕もすっかりpre_get_postsの虜になっている訳なんですが。
ただ、この間のWord Camp Tokyo 2013のテクニカル座談会で、「pre_get_postsとかって初心者には難しくない?」という話があがったり、
仕事で人にWordPressを教えたりすることがあったりするのですが、WordPressが専門ではない人だとか、デザイナーさんだとか、functions.phpよくわからん!って人にはめちゃくちゃ高いハードルな気がしてます。
「でも、そんな人にもpre_get_postsを使ってほしいナー」とか、「管理画面からデフォルトの値は設定できるんだったら、他のも管理画面からやりたいよナー」
と、思ったので作ってみました。教えてと言われてもちゃんと教えられる自信が無いので、プラグインにしました。pre_get_postsを簡単に使うにはいいと思ってます。細かいことはできませんが。
そんなわけで、ちょっとでも便利そうだなと思ったら、使ってみてください。
フィードバックは@Toro_Unitや、https://github.com/torounit/ppppやら、フォーラム等でいただければ幸いです。
余談ですが、制作時間より、「略称をPPPPにしたいがために、Pから始まる単語を探しまくった時間」のほうが長かったです。どういうこっちゃ。
記事がずっと下書き状態のままでした。。。
先月末の話ですが、Custom Post Type Permalinks 0.9.3.3をリリースしました。
WordPress › Custom Post Type Permalinks « WordPress Plugins
カスタム投稿タイプのスラッグと、固定ページのスラッグがコンフリクトした場合の処理を追加しました。
has_archive => trueのときは、カスタム投稿タイプのアーカイブを、falseであればアーカイブページが生成されないので、固定ページが表示されます。
投稿タイプの著者アーカイブは “/投稿タイプスラッグ/author/著者名/”、dateアーカイブは、”/投稿タイプスラッグ/date/年/月/日”になります。この仕様はこのバージョンでの修正では無いですが、パーマリンク生成のロジック変更のため、アクセスできていたものができなくなる場合があります。
また、デフォルトのパーマリンク設定に拡張子をつけた場合にカスタム投稿のパーマリンクがおかしくなるバグ等を修正しました。
その他、細かい修正を行っています。よろしくお願いします。
ブログを書くまでがWordCampです!というわけで、WordCamp Tokyo 2013に参加して参りました。相変わらず、凄い人の数でしたね。
そんなわけで、WordPressカルタに参加させていただきました。幼少の頃、上毛かるたをやっていたグンマーな僕としては、負ける訳にはいかない!ということで、一応、優勝?いたしました。
そんな訳で、WordPressカルタ
と、
スタッフTシャツいただきました!
そして、嬉しいことに、「Custom Post Type Permalinks」の札があるではありませんか。
こういうのってなかなか嬉しいですね。使ってもらっている実感とかが得られるというか。とりあえずプラグイン制作っていいもんだなと思いますよ。とりあえず話の種になるし、決して楽ではありませんが得るものも大きいなと個人的には感じています。
とりあえず、開発がんばります。。。壇上でもしゃべりましたが、Pull Request、Patch、バグレポート、お酒待ってます!
開発レポジトリ:https://github.com/Toro-Unit/custom-post-type-permalinks
他にも、PHPカンファレンスのほうでも、ためになるセッションがあったり、WordPress Codex 日本語版の編集やってみようと決心したり、いろいろ、考えさせられることも多かったです。また、その辺のアウトプットは別にやっていきたいと思います。
なかなか、人が多くて、ご挨拶できなかった方々も大勢いるので、東京や名古屋の勉強会にももう少し参加したいなと思いました。
あ、あとダイエットします。今度はウソじゃないです。
最近は PHP 5.3 がいろんなレンタルサーバーでもメジャーになってきて、PHP 5.2 は若干レガシーかな。みたいな雰囲気ですね。
そんなPHP 5.3ですが、無名関数が使えます。
[php]
$foo = function( $bar ) {
echo $bar;
};
$foo("ほげ"); //ほげ
[/php]
こんな感じで、書けるようになりました。JavaScriptみたいに書けますね!
前から、create_functionという関数はあったんですが、こんな感じで文字列で渡さないとなので、とても読み書きがしづらいんですよね。匿名関数というやつです。
[php]
$foo = create_function( "$bar", "echo $bar;" );
$foo("ほげ"); //ほげ
[/php]
そんなわけで、add_action, add_filter もこんな風に書けます。
[php]
add_filter( "hoge", function( $param ){
$param = $param + "ほげ";
return $param;
} );
add_action( "hoge", function( $piyo, $fuga ){
echo $piyo + $fuga;
}, 10, 2 );
[/php]
時と場合を選ぶとは思うんですけど、アクションフック・フィルターフックは無名関数を使って書いた方が、関数名の衝突等も発生しないのでいい場合も多いかもしれません。また、チームのメンバーがJavaScript得意って場合もこっちの方が読み易いかも知れません。
とりあえず、オーバーライドや、remove_action, remove_filer が想定される場合は避けましょう。
Advanced Custom Fields に最近お世話になりっぱなしです。カスタムフィールドが手軽に扱えるし、ユーザーにもかなり優しいUIを作り易いし。
そんな訳でACFを使ってちょっとした機能を作るときのTipsです。
よく、記事の公開、公開中の記事の公開時には、publish_postというアクションフックが実行されます。しかし、この段階では、カスタムフィールドの値はデータベースに保存されていません。
なので、$_POSTで送信されてきた値をとってきます。
[php]
add_action("publish_post","my_publish_post");
function my_publish_post( $post_id ) {
$acf_field = get_field_object( "hoge" );
$acf_field_key = $acf_field["key"];
if( isset( $_POST["fields"][$acf_key] ) {
$field_value = $_POST["fields"][$acf_key];
//ここに処理。
}
}
[/php]
hogeというキーで設定したフィールドの値はこんな感じで取得できます。
これに、WordPressで記事の公開期間を簡単コントロール!カスタムフィールドに開始・終了日時を指定するだけでOKのクラス | Pimp My Site
を組み合わせて、
[php]
class PM_Schedule_Post_ACF extends PM_Schedule_Post {
protected function get_meta( $key ) {
$val = ”;
$acf_field = get_field_object( $key );
$acf_key = $acf_field["key"];
if ( isset( $_POST["fields"][$acf_key] ) ) {
$field = htmlspecialchars( $_POST["fields"][$acf_key], ENT_QUOTES );
}
else {
$val = parent::get_meta ( $key );
}
return $val;
}
}
add_action( ‘after_setup_theme’, function() {
new PM_Schedule_Post_ACF( "pubstart", "pubend", "公開終了" );
});
[/php]
みたいな感じで使ってます。実際に使っているのはもう少しガリガリいじっているのでまたそれは後日アップします。
管理画面のUIをACFで統一できるので、かなり使い勝手の良い管理画面を作れると思います!
この間、WordPressのマルチサイトモードで、8サイトくらいあるサイトを作りました。
一つのサイトですが、更新コンテンツがとにかく大量にあっりました。
そのコンテンツがカスタムフィールドばりばり使ったり、デザインがいろいろ違っていたり、求められる機能がいろいろ違ったりしていて、カスタム投稿やタクソノミーでは、開発しづらいし運用も大変だろうな・・・・ということで、マルチサイトで子テーマを6つくらい作りました。そのときのやったこと、やれば良かったことなどなど。
要は、あるテーマを元にしてそのテーマを一部だけ改変したようなテーマを作成できる機能です。ただ、読み込み順は子テーマ→親テーマとなるので、子テーマに足りないものを親テーマから保管する機能と言ったほうが正確かも知れません。
継承って言い方をしていますが、プログラミングにおけるクラスの継承とは全く別物なので注意が必要です。
なので、get_header()とかを子テーマで、書いた場合、子テーマ内のheader.phpを探しにいって、なかった場合、親テーマのheader.phpが呼ばれます。
また、子テーマにarchive.php、親テーマにcategory.phpがある場合は、カテゴリーページにアクセスしたら親テーマのcategory.phpが呼ばれるようです。まぁ、そうじゃないと、index.phpを作ったら全部のテンプレートを上書きってことになってしまいますもんね。
子テーマとしてテーマを作成するためには、style.cssの最初のテーマ用コメントに Template: 親テーマのディレクトリ名とするだけです。また、子テーマの場合、index.phpが無くても大丈夫です。
[css]
/*
Theme Name: 子テーマ
Template: parent
*/
[/css]
また、子テーマの子テーマ、孫テーマみたいなのは作成できません。1世代までです。
正直全部は説明できませんが、とりあえず、
の値は変わります。
stylesheet・・・シリーズは子テーマ、templateシリーズは親テーマの情報を返します。
なので、テーマ内で使う画像やCSS等、共通のリソースは親テーマに突っ込んでおく&なるべくtemplateシリーズでの記述ををお勧めします。
また、is_child_theme()という関数もあるようです。
functions.phpだけは存在すれば読み込まれない、という挙動ではなく、子テーマのfunctions.php→親テーマのfunctions.phpの順で両方読み込まれます。カスタム投稿・タクソノミーの設定は、子テーマのfunctions.phpに記述するといいかもしれません。
また、
子テーマのfunctions.php で同名の関数があれば、子テーマの関数が使用されます。
という記述が日本語版Codexにありますが、これは、ちょっと言葉足らずで、そのまま同名の関数を書くと、「Cannot redeclare」のエラーを吐いてしまいます。なので、親テーマに再定義可能な関数を作る場合は
[php]
if ( ! function_exists( ‘parent_function’ ) ) {
function parent_function() {
// 処理内容
}
}
[/php]
としてあげる必要があります。英語版のCodexにはここら辺のこともちゃんと書いてあります。Child Themes « WordPress Codex
また、テーマで使う変数も保護しないと上書きされてしまうのでここら辺は注意が必要です。変数の上書きはエラーにならないので、定数にしておく等の工夫が必要です。
ちゃんと使いこなせば、いろいろ便利な機能ですが、ちゃんと設計しないと、「別々にテーマを作った方が、楽だった」になんてことになりかねない機能でもあります。
なので、いくつか注意事項、というより現時点で僕が気を使っているルールです。
一番最初にマルチサイト+子テーマでサイトを作ったときに、親テーマを親サイト(ルートサイト)に設定していたために、死ぬほど苦労した結果、子テーマをやめた。なんて失敗もありました。
親サイトはトップページなど、再利用性が低いものが入ることが多いですし、front-page.phpや、home.phpなど、テンプレートの読み込み順の優先度が高いものを使うことも多いです。これを子テーマ側でいちいち作成するのはとても面倒。無駄。これだけは絶対やってはいけないです。
また、親テーマを実際に利用していると、「このサイトではカテゴリーも月別アーカイブも全部一緒でいいのに・・・・」みたいなことが発生し易いです。
なので、親テーマに置くのは、ほんとに共通で使い回す部分だけ&テンプレートの読み込み順が低いもの例えば、
等に留めましょう。
別に子テーマを使ったりしなくてもという話でもあるんですが、マルチサイトは基本的に大きな案件にならないと使わないとは思いますが、そうなってくると、どんどん全部で使い回すようなカスタマイズが、functions.phpに蓄積していきます。
ただ、管理画面のカスタマイズなど、テーマとの関連性が薄いもの、すべてのサイトで活用するものはfunctions.phpではなく、プラグインにして極力テーマの見通しを良くしましょう。カスタム投稿タイプ等は冗長になりがちなので、プラグインで関数を作るなりクラスを作り、それをテーマで使い回す等が便利だと思います。
をプラグインとかfunctions.phpに書いておくと、site-hogeみたいなクラスを吐くので便利かもしれません。特にテーマを識別する手段が無いので。。
特にテーマを別環境で作っているときは気をつけたいのですが、現在のサイトを識別する手段が、グローバル変数の$blog_idくらいしか無かったと思います。ただ、テーマにIDを直書きするのはメンテナンス性を欠くので、get_id_from_blogname( “hoge” )とかで、パスで指定する方が設定とテーマの分離ができて良いのかなと思います。
前回の記事でもそんなとき使えるものを書きました。
https://torounit.com/blog/2013/04/25/1514/
WordPressのマルチサイト機能3.0からMUと統合されたまだまだ新しい機能です。対応していないプラグインもあります。僕のリリースしているCustom Post Type Permalinksもちゃんと対応できておりません(汗)
またカスタム投稿との棲み分けとかも考えないといけない部分があります。
ただ、ちゃんと使いこなせれば、更新コンテンツが多い、ユーザーが多い案件等でもかなり使い易い構築ができるんじゃないかな・・・と思っています。
最近マルチサイト案件が多かったりするのですが、各ブログを横断してリンクをつないだりみたいなことをたくさんやりました。
扱うサイトも多く、ブログを削除して作り直して・・・みたいなことが結構あったのですが、そのときに当然blog_idもかわってしまいます。(まぁそりゃそうだよね)
で、マルチサイトの肝になるところといえば、switch_to_blog でブログを切り替えてあーだこーだすることだとは思うのですが、これが、
[php]
switch_to_blog(1);
[/php]
みたいな感じで、変更先のブログのIDを指定せねばならないのです。これがちょっと使い勝手が悪いし、テーマを見たときにどこのブログに変わったのか、よくわかりません。
という訳でソースを眺めていたら、get_id_from_blogname( $slug )といういかにもな関数がありました。
example.com/hoge/ もしくは hoge.example.com
という子サイトがあった場合、
[php]
get_id_from_blogname( "hoge" );
[/php]
とすると、blog_idを教えてくれるので、
[php]
switch_to_blog( get_id_from_blogname( "hoge" ) );
[/php]
といった感じで、サイトパスで切り替えることができます。こっちの方が解り易いですね。テーマだけ別環境で開発といった場合でもちょっとは反映作業などもスムーズになるのではないでしょうか。
まぁ、案件も終盤になった頃に見つけたのですがね・・・・
マルチサイトは発展途上なイメージですが、ちゃんと使うと結構いろいろなことができそう!
Custom Post Type Permalinksの最新版をリリースしました。
変更内容は以下の通りです。
has_archiveがfalseのときはアーカイブのためのパーマリンクを生成しないようにしました。おかしくなったときは、has_archiveをtrueにしてみてください。
wp_loadedでカスタム投稿タイプをすべて取得して行っていたパーマリンク追加をregistered_post_type後に行うようにしました。WordPressの通常の挙動に近いので不具合等も減ったはず・・・・
git-svnでトラブル多発でバグもあると思いますので、なにかあれば@Toro_Unitまでご連絡ください。
寄付も受付中です。ビールとかビールとか大好きです。欲しいものリスト
最近、メインブラウザをFirefoxからchromeに変えたせいか、はたまたパソコンを見ている時間が多いせいかわかりませんが、ブログを書くときの文字が小さくて困ります。
ビジュアルエディタはadd_editor_style()とかでカスタマイズできるんですが、テキストエディタはそうもいかない・・・・・
でも僕としては、HTMLタグを使う方が楽なんですよね。
というわけで、functions.phpでごにょごにょします。
[php]
function change_textarea_style() {
?>
<style type="text/css">
#wp-content-editor-container textarea.wp-editor-area {
font-size: 14px;
font-family: Consolas, "ヒラギノ角ゴ Pro W3","ヒラギノ角ゴ Pro","Hiragino Kaku Gothic Pro W3","Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, Osaka, sans-serif;
}
</style>
<?php
}
add_action( "admin_head", "change_textarea_style" );
[/php]
font-familyとかは、自分が使いやすいものを入れておけばなんでもいいです。別に、ガツガツHTMLは書かないのであれば等幅フォントにこだわる必要ないですし。
自分色に染め上げれば、記事を書く意欲も自然と湧いてきますよね。あ、ディスプレイが小さいんじゃ・・・・とかは言ってはいけません(笑
Custom Post Type Permalinksをアップデートしました。
という不具合を修正しました。
その他、細かいバグフィックスを行いました。
http://wordpress.org/extend/plugins/custom-post-type-permalinks/
また、いつも通り、何かありましたら、@Toro_Unitまでリプライください。m(_ _)m
最近カスタム投稿タイプやら、マルチサイトでのブログ一覧をいじくることがそこそこあったのですが、ちょっと注意したいことがあったのでまとめ。
query_posts() 関数はメインの WordPress ループだけを変更するためのものです。新たなループを作るためのものではありません。メインループの他にループが必要な場合は、get_posts() を使ってください。メインループの他で query_posts() を使用すると、メインループが不正な状態になり期待する結果が得られません。
query_posts() 関数はページのメインクエリを上書きし、置き換えます。他の目的で使用しないでください。
query_posts() 関数は新しい WP_Query オブジェクトを作成し、グローバル wp_query 変数に割り当てます。get_posts() 関数は、グローバルエリアをまったく上書きすることなく新しい WP_Query オブジェクトを作成します。
と Codex に記載されています。 pre_get_posts を使うとこんな問題を起こさずにカスタマイズ出来ます。
テンプレートタグ/query posts – WordPress Codex 日本語版
まぁ、おおざっぱにいえば、WordPressのそのページで使われているループを強制的に上書きしてしまう機能です。通常はURLを解釈して、それを元に記事を探してくるのですが、それを完全に無視します。
"トップページとかでお知らせのタイトルを5件だけ表示する"みたいなときに使うことが多いと思いますが、カスタムページテンプレートで何かの記事一覧を出したり、なんて使い方をすることもたまにあったり。
よくあるトラブルその1ですね。URLには"paged/2"とか書いてあるのですが、query_postsで再設定してしまっているので、うまくいきません。
解決としては、query_postsに「今何ページ目?」という情報を与えてあげればよいので、
query_posts(array( "paged" => get_query_var('paged'), "foo" => "bar" ));
だとかしてあげればOKです。
今回の現象です。なぜか404になってしまいます。
上記の設定ができているのに、うまくいかないということがありました。
WordPressのテンプレート選択は、URLを解釈して読み込まれるわけですが、アーカイブページでは、最後のページが"/page/10"などの場合、"/page/11"だとかはNot Found扱いになり、404.phpが読み込まれます。これはカテゴリーでもカスタム投稿アーカイブでも同様です。
なので、query_postsをarchive.phpなどに書いていたとしても、archive.phpが読み込まれる前にページが存在しないという判定になります。
たとえば投稿が100件あって、WordPressの設定では1ページ当たりの表示件数を10件としている場合に、query_postsで5件しか表示しないようにしていると、11ページ目が存在するかしないかの判定は、WordPressの設定を使うので、すべての投稿が表示されていないのに、Not Foundとなってしまいます。
archive.phpとかarchive-post_type.phpとかcategory.phpだとかで、メインのループを上書きしない。
テンプレートがちゃんと提供されているので、それをちゃんと素直に使いましょう。ということです。
ただしそういうわけにもいかないときもあるとは思いますし、カスタム投稿タイプごとに表示件数もデザインも変えたい!ということはあるかと思います。
そんなときは、pre_get_posts を使いましょう。
管理画面から、投稿件数を投稿タイプとかタクソノミーとかで弄れるプラグイン作っているので、そちらもどうぞ。
URL から得られたクエリを変更することはトラブルの元になります。条件分岐タグ のようなページの判定を組み合わせることで、URL を一切変えることなく投稿 の見せ方をカスタマイズすることができます。
とCodexにも記載されております。pre_get_posts で安全に使いましょう。