サイト内検索
Cocoonフォーラム
書き込みの前に以下の3点をご確認ください。
何を書き込んだら良いか分からない場合は、以下のテンプレートをコピペしてご利用ください。
不具合・カスタマイズ対象ページのURL:
相談内容:
不具合の発生手順:
解決のために試したこと:
※文字だけでは正しく伝わらない可能性があるため、スクショ画像の添付もお願いします。
※高速化設定をしている場合は無効にしてください。
環境情報:※↑こちらに「Cocoon設定 → テーマ情報」にある「環境情報」を貼り付けてください。
環境情報の取得方法はこちら。
→ https://wp-cocoon.com/theme-report/
高速化設定を無効にするにはこちら。
→ https://wp-cocoon.com/theme-trouble/
フォーラム利用ガイドリンク
- フォーラムガイドライン
- よくある質問と答え(FAQ)
- サポート対象外のケース
- 原因不明の不具合用トラブルシューティング
- トピックにHTMLを貼り付ける方法(推奨ツール:notepad.pw)
- 真っ白画面でのエラーメッセージの確認方法
- ブラウザ環境チェックツール
- Cocoonカスタマイズ依頼
フォーラム質問後、問題等が解決した場合は結果を書き込んでいただけると幸いです。同様の問題で調べている方には、結果が一番気になる部分となります。
トピックスターター 2019年8月7日 21:57
WordPressにDBのテーブルにwp_termmetaが追加され、カテゴリー・タグページのカスタムフィールドが作成しやすくなりました。
Cocoonでも、「カテゴリ色」以下の設定ではこのタームメタが使用されています。
実際に直接問題が生じたわけではないのですが、独自のタームメタカスタマイズ実装中にCocoonでのwp_termmetaの取り扱いについて問題を感じ、今後のために一応問題となり得る点を共有させていただきます。
以下、wp_postmetaと比較してみるのが分かりやすいかもしれません。
Cocoonではmeta_keyが{taxonomy}_meta_{term_id}、そしてCocoonの全カスタムフィールド値をひとつの配列にまとめたものがmeta_valueとなるよう設計されています。
get_term_metaなど、タームのメタ情報を操作する各関数を使用するだけであれば、特に問題となることはないと思います。
しかし、wp_termmetaに合わせて実装されたWP_Term_Query(get_terms)のmeta_queryを含めて考えると、あまり良い設計ではなさそうです。
WP_Term_QueryはWP_Queryのターム版とも言えますが、例えば「個別の投稿記事のうち、Cocoonの"インデックスしない"を選択した記事を一覧で取得したい」場合、wp_postmetaのmeta_key'the_page_noindex'から取得することができます。
一方、Cocoonで用意されているterm_metaだとmeta_keyがターム毎に独立してしまっており、またmeta_valueも複雑になっていることから、meta_queryを使用するのが困難になってしまっています。
wp_termmetaにはmeta_key・meta_valueに加え、各term_idも合わせて保存されるため、少なくともmeta_keyにterm_idを含める必要はないかと思います。
新たにタームメタを用いた機能を実装する場合は、上記のようなWordPressの仕様を考慮して実装した方がよさそうです。
2019年8月8日 22:25
カテゴリーで言えば、この部分ですよね。
https://github.com/yhira/cocoon/blob/24a428b1988a0126f60c3d7b547f3216061bed20/lib/content-category.php#L18
https://github.com/yhira/cocoon/blob/24a428b1988a0126f60c3d7b547f3216061bed20/lib/content-category.php#L31
https://github.com/yhira/cocoon/blob/24a428b1988a0126f60c3d7b547f3216061bed20/lib/content-category.php#L235
wp_postmetaのmeta_key'the_page_noindex'で例えるとすると、キーがthe_page_noindex_{post_id}になっているということですね。
だとしたら、意味のないID指定ですよね。
うーん、どうしよう…。
とりあえず、category_metaをキーにして保存もしておいて、読み込み時category_metaキーで読み込めない場合は、category_meta_{term_id}も取得して値を読み込むようにしたほうが良いのだろうか。
余計な処理は増えるけど、その方が後々分かりやすいような気がする。
トピックスターター 2019年8月8日 23:42
はい、挙げられたコードの部分です。
wp_termmetaには、単体のデータとしてterm_id・meta_key・meta_valueがセットで保存されており、get_term_meta関数はひとつのterm_idとmeta_keyから特定のmeta_valueを取得してくる一方、WP_Term_Queryクラスのmeta_queryは指定したmeta_key(とmeta_value)にマッチするterm群を取得してくるよう実装されています。
meta_keyがterm_id毎に独立してしまっていることにより、共通条件のクエリでは取得できません。
typeパラメータやcompareパラメータでmeta_valueを条件指定できることまで考慮すると、個別のメタ情報におけるmeta_valueはなるべく整理してシンプルにしておくのがよさそうなので、私がカスタマイズで新たに加えた箇所は取得データが1対1となるように切り分けて保存する形にしました。
Cocoonの例で言うと、カテゴリ色でひとつ、タイトルでひとつ…といった感じです。
現在のデータに修正を加えるのであれば、保存する際(save_extra_category_fileds関数)は新たに整理した形のタームメタに保存するようにし、取得する際(get_category_meta関数)は新タームメタ⇒(データがセットされていない場合のみ)旧タームメタになりそうですね。
メタ情報を切り分ける場合は、save_extra_category_fileds関数での保存時に$_POST['cat_meta']を要素ごとに繰り返しupdate_term_metaすることで対応可能です。
2019年8月9日 20:06
今回、IDごとにキーを指定しているのと、配列で保存しているという2つの問題点がありますね…。
なんでこんな仕様にしてしまったんだか…。結構昔なので全部覚えてないです。
多分、あまり深く考えないでやってしまったんだと思います。
私がカスタマイズで新たに加えた箇所は取得データが1対1となるように切り分けて保存する形にしました。
よろしければ、content-category.phpコードをnotepad.pw等で、見せていただいて、命名とコードなどを参考にさせていただくことは可能でしょうか。
追記:とりあえずブランチ側で修正しました。
2019年8月9日 20:11
wp_postmetaに命名を合わせて、色だったらthe_category_color, the_category_text_colorとかにした方が良いのかもしれませんね。
2019年8月9日 20:17
とりあえずは、こちら側でブランチを切って修正してみようと思います。
2019年8月9日 21:58
とりあえず、こんな感じで修正してみました。
https://github.com/yhira/cocoon/commits/save_extra_category_fileds
https://github.com/yhira/cocoon/commit/324bda0dec5aff26f986869caf457f064403307c
これで、以前の保存情報取得できつつも、新しいwp_termmetaに保存できるようになったのではないかと思います。
もう少し、動作確認してみてタグの方も修正しようと思います。
トピックスターター 2019年8月10日 00:26
ぱっと見た感じでは問題なさそうなので、とりあえずテストして詳しく確認してみようと思います。
問題が起こらない限りは修正の必要はありませんが、
私がカスタマイズで新たに加えた箇所は取得データが1対1となるように切り分けて保存する形にしました。
について、一応私の命名やコードを書いておきます。
命名については、私は主なカスタマイズはアップデートしやすいようにプラグインにまとめているため、meta_keyは[プラグイン名]_[キー名]といった感じで命名しており、基本的にCocoonの仕様が変更されても問題ありません。
save_extra_category_fileds関数での保存時に$_POST['cat_meta']を要素ごとに繰り返しupdate_term_metaする
コードについては、上記の説明をコードにしておけばよかったのですが、name="example[meta_key]"と配列のままで送信し、$_POST['example']をもとにforeach内で繰り返しupdate_term_metaする形にしました。
以前のCocoonからだと、
function save_extra_category_fileds( $cat_id ) {
if ( isset( $_POST['cat_meta'] ) ) {
$keys = array_keys( $_POST['cat_meta'] );
foreach ( $keys as $key ) {
update_term_meta( $cat_id, $key, $_POST['cat_meta'][$key] );
}
}
}
のような形と言えます。
その他は修正版のコードとおよそ同じ形になっています。
わいひら reacted
2019年8月10日 20:23
ご確認と、コードありがとうございます。
今のところ、僕の環境でいろいろ動作確認しても問題ないので、タグ部分も変更してみようと思います。
修正したらまた書き込みます。
2019年8月10日 22:01
一応、タグも修正しておきました。
https://github.com/yhira/cocoon/commits/save_extra_category_fileds
https://github.com/yhira/cocoon/commit/a18b4a369ee6f1645b61eb54200390469f51a92d
これも、とりあえず動作確認した限りでは、大丈夫そう。
トピックスターター 2019年8月11日 02:06
カテゴリー・タグそれぞれの動作をざっと確認した限りでは問題なさそうです。
アプデ後の利用者向けに書き加えておくと、各フィールドの値を取得するのにget_term_meta関数から各々のメタ情報を取得する関数に置き換えたことで、タイトルを設定するフィールドの初期値にカテゴリー名が入るようになったのが変更点といったところでしょうか。
実際の動作に影響はありません。
最終的に不要になった旧メタ情報については、delete_term_metaなどで削除処理を加える予定はありますでしょうか?
なさそうであれば、本件の実装に合わせて自分で処理を加えようと思いますが。
わいひら reacted
2019年8月11日 12:51
タイトルを設定するフィールドの初期値にカテゴリー名が入るようになったのが変更点といったところでしょうか。
これは、意図しないものでした。未入力の場合はカテゴリー名が入らないように修正しました。
あと、新しい値に空欄を入力したときに、反映されない不具合があったので修正しておきました(今のところカテゴリーのみ)。
https://github.com/yhira/cocoon/commit/85fab2937953591dc68103c921c0fb08ae2aa027
加えて、一応、古い配列の値も設定を保存するようにも変更しました。新しい値と、古い値が別々だと、ややこしいような気もして。
最終的に不要になった旧メタ情報については、delete_term_metaなどで削除処理を加える予定はありますでしょうか?
今のところ新しいキーにデータが保存してない場合は、旧データ(get_the_category_metaで読み込んでいる配列)を読み込む必要があるのと、あっても負荷はそこまで変わらないと思うので、今のところ削除は考えていません。
2019年8月11日 13:21
すいません。上記のものは、旧データを読み込まない不具合がありました。
現在修正中です。
2019年8月11日 13:21
一応修正はしてみたものの、これだとget_term_metaを読み込んだ後、空欄だったらget_the_category_metaをもう一度読み込む必要があるのが、ちょっと気持ち悪い。
https://github.com/yhira/cocoon/commit/847a5b1db405e12c28f8b00b8770194d529e2830
とりあえずの修正。
2019年8月11日 13:37
よく見たら、get_metadata→get_metadataで失敗したときの返り値がflaseに限定されていたわけではないっぽいのが原因だったかも。
https://developer.wordpress.org/reference/functions/get_term_meta/
https://developer.wordpress.org/reference/functions/get_metadata/
これじゃ、このように書くとダメな場合もあるのかも。
function get_the_category_color($cat_id = null){ $res = get_term_meta( $cat_id, 'the_category_color', true ); if ($res !== false) { return $res; } else {//旧バージョン対応
トピックスターター 2019年8月11日 14:30
get_term_metaは実際にはget_metadataが処理しているので、meta_keyの有無にかかわらずsingleパラメータがtrue→空文字、false→空配列を返す形になっています。
その代わりに、meta_keyの有無を確認する方法としてmetadata_existsが存在します。
最終的に不要になった旧メタ情報については、delete_term_metaなどで削除処理を加える予定はありますでしょうか?
私が上記の確認を行ったのは「不要なデータは削除してデータベースを見やすく整理すべき」との考えもありましたが、term_meta関数の仕様も考えてのことでした。
空欄で更新を行った際の不具合については見落としていましたが、旧データと新データを混在したままで取り扱おうとすると、やはり少し複雑になってしまいます。
最初の修正版での動作から、
- 既存のカテゴリー編集画面を開く
- 旧データから各フィールドの設定が読み込まれる
- 適宜編集したあとに更新を行う
- 編集内容が新メタデータとして格納される
となっているので、4のedited_term時点で該当するterm_idに紐づく旧データは少なくとも必要なくなります。
よって、更新に合わせてこの旧データのみdelete_term_metaを使用しても問題なさそうと思いました。
旧データから新データに移行するためにupdate_term_metaとdelete_term_metaを使用するタイミングはedited_termでなくてもよいですが、新旧両方のデータが混在し続ける形で考えるのではなく、何らかの動作を区切りに新データのみを扱う形に切り替える方向で考えた方が各コードの動作を複雑化しなくて済むのではないでしょうか?
わいひら reacted
トピックスターター 2019年8月11日 14:51
- get_the_category_metaで旧データを取得する
- 旧データ配列内の各要素を新データのmeta_keyに対するmeta_valueに入れる
- 新データについてupdate_term_metaを行う
- 旧データについてdelete_term_metaを行う
この一連が動作するポイントは、各ターム編集画面の更新時に個別だろうとアプデ後のテーマ読み込み時に一括だろうと、動作する箇所であればどこでもOKだと思います。
この動作を区切りとして、区切りより前は
- 旧データのmeta_keyは存在する
- 新データのmeta_keyは存在しない
区切りより後は
- 旧データのmeta_keyは存在しない
- 新データのmeta_keyは存在する
といった感じで判断材料にできます。
すると、旧データに対するコードと新データに対するコードを切り分けることができ、最終的に不要なデータが残ることもありません。
2019年8月11日 17:13
metadata_existsの存在を知りませんでした。
それを使用して、判定するように変更しました。
https://github.com/yhira/cocoon/commit/d81bdcb3eb0e8ddcbd487ec1ff12085bb9cf39f2
何らかの動作を区切りに新データのみを扱う形に切り替える方向で考えた方が各コードの動作を複雑化しなくて済むのではないでしょうか?
よくよく考えたら、edited_term時、新しい値を保存したのであれば、古い配列の値をわざわざ新しくして保存する必要もなく、削除してしまえば良いですよね。
削除するように変更しておきました。
https://github.com/yhira/cocoon/commit/39dfea27246419daa1d19ec900d13fe813ceaaa7
トピックスターター 2019年8月12日 13:32
改めて修正後のテーマをインストールし、チェックしてみました。
function get_the_category_title($cat_id = null, $is_cat_name = true){
if (term_metadata_exists($cat_id, 'the_category_title')) {
return get_term_meta( $cat_id, 'the_category_title', true );
} else {//旧バージョン対応
$meta = get_the_category_meta($cat_id);
if (!empty($meta['title'])){
return $meta['title'];
} else {
//タイトルが存在しない場合はカテゴリ名を利用する
if ($is_cat_name) {
return get_category($cat_id)->name;
}
}
}
}
カテゴリータイトルの取得について、'the_category_title'に移行後のタイトルは無条件でreturnしてしまっているため、空の場合に一部カテゴリー名が表示されません。
function get_the_category_content($cat_id = null){
if (term_metadata_exists($cat_id, 'the_category_content')) {
return get_term_meta( $cat_id, 'the_category_content', true );
} else {//旧バージョン対応
if (!$cat_id) {
$cat_id = get_query_var('cat');
}
$meta = get_the_category_meta($cat_id);
if (!empty($meta['content']))
$content = $meta['content'];
else
$content = category_description($cat_id);
}
$content = wpautop($content);
$content = apply_filters( 'the_category_tag_content', $content );//カテゴリー・タグ本文共通
$content = apply_filters( 'the_category_content', $content );
return $content;
}
同様に、カテゴリー本文についても無条件でのreturnによりコンテンツの整形が行われません。
わいひら reacted
2019年8月12日 18:12
ありがとうございます。
カテゴリータイトルの取得について、'the_category_title'に移行後のタイトルは無条件でreturnしてしまっているため、空の場合に一部カテゴリー名が表示されません。
タイトルが空欄の場合、公開ページで通常のカテゴリ名が必要な場合に、空文字になる恐れがありますね。
双方とも、修正しておきました。
https://github.com/yhira/cocoon/commit/7fc3a167c8cc6071e83237b098b2ae7c72c94e1d
トピックスターター 2019年8月14日 00:03
確認した限りでは、今のところその他に大きな問題は確認されません。
特に問題なさそうでしたら、アップデート内容に加えても大丈夫なのではないでしょうか。
修正ありがとうございました。
わいひら reacted
2019年8月14日 17:42
僕もいろいろ確認してみた限りでは大丈夫そう。
とりあえずmasterにはマージしてプシュしておきました。
ご確認と、ご助言ありがとうございます!
問題の解決に至った場合には、トピック冒頭の「解決済み」をクリックしていただけますと幸いです。
また、有用な回答があった場合は返信右下にある「いいね!」もご活用ください。回答者の励みになります。
(CC BY-ND 2.1)準じていれば(リンクを貼っていただければ)転載も自由です。カスタマイズ記事を書く際にコード等をコピペ利用していただいて構いません。
フォーラムの使い方がよくわからない場合は、テストトピックで自由にテストしていただいて構いません。
最近の書き込みはこちら。
詳細なカスタマイズ依頼をするならこちら。