web-dev-qa-db-ja.com

ポストキャスト時にすべてのカスタムフィールドを同じフィルタに通りますか。

投稿のすべてのカスタムフィールドをフィルタリングする方法はありますか?

私が持っている非常に基本的な単純さのために仮定しよう:

の標準フィールド:

  • タイトル
  • ポストボディ

カスタムフィールド:

  • 著者
  • ISBN
  • 見積もり

ページの読み込み時に、各カスタムフィールドの値の最後に123456を追加するとしますが、これはフィルタを使用して行うとします。どのadd_filterでこれを達成できますか?ちょっとしたコードの書き方が役に立つでしょう。

現在のトップアンサーに従って編集してください:

一番上の答えを見つけた後、私はそれが最初の分野でしか働かない問題に出くわしました。私はそれから私が各要素を通過する必要があることに気づきました、そしてこれは私が持っているものです。奇妙なのは、データが損なわれていないように見えますが、ページに新しいデータが表示されないことです。以下のコードにコメントがあります。

function my_post_meta_filters($null, $post_id, $key, $single){
    if(is_admin() || (substr($key, 0, 8) != '_author_' && substr($key, 0, 7) != '_quote_')){
        return $null;
    }

    static $filtered_values = NULL;

    if(is_null($filtered_values)){
        $cache = update_postmeta_cache(array($post_id));
        $values = $cache[$post_id];

        //must loop through all the fields or else only the first field is affected
        foreach($values AS $valkey => $value){                                   
            if(substr($key, 0, 8) == '_author_' || substr($key, 0, 7) == '_quote_'){
                $filtered[$valkey] = filtered($values[$valkey][0]);
                $filtered[$valkey] = maybe_serialize($filtered[$valkey]); //at this point the data is correct and even reserialized where expected
                $filtered_values[$valkey] = $filtered[$valkey];
            }
        }
        return $filtered_values;
    }
}
add_filter('get_post_metadata', 'my_post_meta_filters', 0, 4);

function filtered($it){
    if(!is_array($it) && !is_serialized($it)){
        $filtered = apply_filters('number_filter', $it); //adds numbers to the end
    } else {       
        //otherwise we ran into a serialized array so lets unserialize and run each part through our function
        $unserialized = maybe_unserialize($it);
        $filtered = array_map('filtered', $unserialized);
    }

    return $filtered;
}
5
Shawn

内部的にポストメタは、ほとんどフィルタリングできないオブジェクトキャッシュを介して処理されます。

投稿メタデータをフィルタリングする唯一の機会は、 'get_post_metadata' を使用することですが、メタデータが利用できないときにそのフィルタがトリガーされるので、フィルタリングするものはありません。それらをフィルタリングすることよりも結果を短絡することを意図していました。

だから私が提案する解決策は:

  1. そのフィルタで実行される関数を起動し、そして手動でメタデータを取得する
  2. 取得した後、取得したばかりのデータをフィルタできるようにカスタムフィルタをトリガします。
  3. 後続の呼び出しでdb queryを再実行しないように、フィルタリングされた値を静的変数に格納します。
  4. 最後にカスタムフックにコールバックを追加し(ポイント#2で追加)、データをフィルタリングします

そこで、まずフィルタを追加します。

add_filter( 'get_post_metadata', 'my_post_meta_filters', 0, 4 );

それからフッキングコールバックを書きます

function my_post_meta_filters( $null, $pid, $key, $single ) {
  if ( ! in_array( $key, array( 'author', 'ISBN', 'quote', '' ), TRUE ) || is_admin() ) {
    return $null;
  };
  static $filtered_values = NULL;
  if ( is_null( $filtered_values ) ) {
    $cache = update_meta_cache( 'post', array( $pid ) );
    $values = $cache[$pid];
    $raw = array(
      'author' => isset( $values['author'] ) ? $values['author'] : NULL,
      'ISBN'   => isset( $values['ISBN'] )   ? $values['ISBN']   : NULL,
      'quote'  => isset( $values['quote'] )  ? $values['quote']  : NULL,
    );
    // this is the filter you'll use to filter your values
    $filtered = (array) apply_filters( 'my_post_meta_values', $raw, $pid );
    foreach ( array( 'author', 'ISBN', 'quote' ) as $k ) {
      if ( isset( $filtered[$k] ) ) $values[$k] = $filtered[$k];
    }
    $filtered_values = $values;
  }
  if ( $key === '' )
     $filtered_values;
  if ( ! isset( $filtered_values[$key] ) )
     return;
  return $single
    ? maybe_unserialize( $filtered_values[$key][0] )
    : array_map( 'maybe_unserialize', $filtered_values[$key] );
}

この関数をコードに含めると、カスタム'my_post_meta_values'フィルタを使用してカスタムフィールドをフィルタできます。

ほんの一例です。

add_filter( 'my_post_meta_values', function( $values, $post_id ) {

  // append '123456' to all values

  if ( is_array( $values['author'] ) ) {
    $values['author'][0] .= ' 123456';
  }
  if ( is_array( $values['ISBN'] ) ) {
    $values['ISBN'][0] .= ' 123456';
  }
  if ( is_array( $values['quote'] ) ) {
    $values['quote'][0] .= ' 123456';
  }

  return $values;

}, 10, 2 );

このフィルタを有効にして、次の操作を行います。

echo get_post_meta( $post_id, 'author', TRUE );

そしてあなたの "author"カスタムフィールドは "Shawn"に設定されていますが、出力は "Shawn 123456"です。

my_post_meta_filtersget_post_custom とも互換性があることに注意してください。

2
gmazzap