web-dev-qa-db-ja.com

配列としてpost_meta値を更新する方法

以下のように私はupdate_post_meta()を使用して複数の選択オプションとして私のナビゲーションメニュー項目内に新しいカスタムフィールドを作成しました

function YPE_update_custom_fields($menu_id, $menu_item_db_id, $menu_item_data) {
    if (is_array($_REQUEST['menu-item-content-multiple'])) {
        update_post_meta($menu_item_db_id, '_menu_item_content_multiple', $_REQUEST['menu-item-content-multiple'][$menu_item_db_id]);
    }
}
add_action('wp_update_nav_menu_item', 'YPE_update_custom_fields', 10, 3);

function YPE_setup_custom_fields($item) {
    $item->content_multiple = get_post_meta($item->ID, '_menu_item_content_multiple', true);
    return $item;
}
add_filter('wp_setup_nav_menu_item', 'YPE_setup_custom_fields');

それから私は以下のようにWalker_Nav_Menu_Editファイルに新しいフィールドを追加します

_編集済み_

<?php
$select_options = array (
    'key_1' => 'option1', 
    'key_2' => 'option2', 
    'key_3' => 'option3'
); 
?>
<p class="field-content-multiple description description-thin">
<label for="edit-menu-item-content-multiple-<?php echo $item_id; ?>">
    <?php _e( 'Multiple Content' ); ?><br />
    <select name="menu-item-content-multiple[<?php echo $item_id; ?>][]" id="edit-menu-item-content-multiple-<?php echo $item_id; ?>" class="widefat code edit-menu-item-content-multiple" multiple="multiple">
            <?php foreach ($select_options as $key => $value): ?>
                <option value="<?php echo $key; ?>"  <?php echo selected(in_array($key, $item->content_multiple)); ?>><?php echo $value;?></option>
            <?php endforeach ?>
    </select>
</label>
</p>

私のコードは問題なく単一の選択ボックスで動作しますが、複数の選択ケースでin_array()を使用するとこのエラーが返されます。

Warning: in_array() expects parameter 2 to be array, null given
5
Shwan Namiq

これをして:

$item->content_multiple = get_post_meta($item->ID, '_menu_item_content_multiple', true);

get_post_meta()の3番目のパラメータをtrueに設定する方法に注意してください。これは、1つの値のみが返されることを意味します。 もしあなたがdocs を読んだなら、3番目のパラメータがfalseであれば、そのメタフィールドのすべての値を含むarray)が得られるでしょう。

メタフィールドは一意でも複数でもかまいません。あるいは、シリアル化されたデータ文字列で一意になることもあります。

実際のところ、あなたのコードはselect multipleからすべての値を一つの単一のメタフィールドに格納しているようです。そのため、リクエストで配列を取得し、それをメタフィールドの単一の値として渡します。メタフィールドの値が配列の場合、WordPress データベースに格納される前にシリアル化された文字列に変換されます。これは関数maybe_serialize()を使って内部的に行われます。メタフィールド、それがシリアル化された文字列である場合、WordPressはそれをmaybe_unserialize()を介して渡します。そのため、シリアル化された文字列は配列に戻ります。

一般的な例で説明しましょう。

これはデータベースに格納される値の配列になります。

$values = [ 'red', 'yellow', 'blue', 'pink' ];

メタキーが「カラー」の場合、2つの選択肢があります。

同じメタキーに対する複数のエントリ

$values = [ 'red', 'yellow', 'blue', 'pink' ];
foreach( $values as $value ) {
    // This method uses `add_post_meta()` instead of `update_post_meta()`
    add_post_meta( $item_id, 'color', $value );
}

これで、$item_idで識別される項目には、colorメタキーのエントリがいくつかあります。次に、3番目のパラメータをfalseに設定してget_post_meta()を使用すると、すべての値を含む配列が得られます。

// You don't really need the set the third parameter
// because it is false vay default
$colors = get_post_meta( $item_id, 'color' );

// $colors should an array with all the meta values for the color meta key
var_dump( $colors );

単一のメタエントリに配列を格納します

この場合、値の配列はデータベースに格納される前にシリアル化されます。

$values = [ 'red', 'yellow', 'blue', 'pink' ];
// WordPress does this automatically when an array is passed as meta value
// $values = maybe_serialize( $values );
update_post_meta( $item_id, 'color', $values );

これで、$item_idで識別される項目は、colorメタキーのエントリを1つだけ持つようになります。値は元の配列を表す直列化された文字列です。次に、エントリが1つしかないため、3番目のパラメータをtrueに設定してget_post_meta()を使用してから、文字列をシリアル化解除して配列を取得します。

$colors = get_post_meta( $item_id, 'color', true );
// WordPress does this automatically when the meta value is a serialized array
// $colors = maybe_unserialize( $colors );

// $colors should be an array
var_dump( $colors );

あなたはあなたのフォームの選択倍数で同じアプローチに従うことができます。

メタキーのエントリが1つだけの場合:

if( ! empty( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) ) {
    $meta_field_value = $_REQUEST['menu-item-content-multiple'][$menu_item_db_id];
    // $meta_field_value will be serialized automatically by WordPress
    update_post_meta( $menu_item_db_id, '_menu_item_content_multiple', $meta_field_value );
}

それから、あなたは配列として値を使うことができます:

 // The value returned by get_post_meta() is unserialized automatically by WordPress
 $item->content_multiple = get_post_meta( $item->ID, '_menu_item_content_multiple', true );

複数のエントリがある場合:

ここでの概念は少し異なります。データベースには同じメタキーを持つ複数のエントリがあるので、各値に新しいエントリを追加するには、add_post_meta()ではなくupdate_post_meta()を使用する必要があります。

if( ! empty( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) ) {
    $values = $_REQUEST[ 'menu-item-content-multiple' . $menu_item_db_id ];
    foreach( $values as $value ) {
        add_post_meta( $menu_item_db_id, '_menu_item_content_multiple', $value );
    }
}

これで、3番目のパラメータをfalseに設定してget_post_meta()を使用できます(これがデフォルト値なので、省略できます)。

$item->content_multiple = get_post_meta( $item->ID, '_menu_item_content_multiple', false );

どちらの方法でも問題ありません。どちらを使用するのがプロジェクト内のデータを整理するのに適しているかを判断する必要があります。

補足:入力データを使用する前に、いくつかの量子化を行う必要がありますが、私はあなたの要件を知りません。ここでは例を示します。

array_map( 'sanitize_text_field', wp_unslash( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) );
10
cybmeta

selected()関数を正しく使っていません。 selected()には1つの必須パラメータと2つのオプションが必要です。あなたの場合は、$ selectedと$ currentを使うのが良いでしょう。

選択名のメタフィールド名の前にアンダースコアがありません。

選択()の場合:

selected( $selected, $current, $echo);

これについてもっと読むことができますコーデックス 選択された関数参照()

あなたの選択は次のようになります。

<select name="_menu-item-content-multiple[]" multiple>
     <?php 
        foreach ($select_options as $key => $value) {
            echo '<option value="'.$key.'" '.selected(in_array($key, $item->content_multiple), $key).'>'.$value.'</option>';
        }
     ?>
</select>
0
Benoti