web-dev-qa-db-fra.com

Enregistrer les cases d'une métabox avec une boucle foreach (argument non valide)

Je suis nouveau dans le développement de plugins Wordpress et j'essaie de créer une liste de cases à cocher (à partir d'une requête WP à associer) à associer en tant que champs personnalisés pour un type de publication spécifique. Rien d’erreur dans la fonction d’affichage, mais si j’essaie de sauvegarder j’obtiens l’erreur

Argument non valide pour la fonction foreach().

Comment vérifier ce que la fonction de sauvegarde voit dans mon tableau global $loop_brands? Quelqu'un peut m'aider à résoudre et à comprendre?

<?php

function brands_display_meta_box( $post ) { 

    global $loop_brands;
    $loop_brands = array();

    wp_nonce_field( plugin_basename( __FILE__ ), 'brands-nonce-field' );

    $args = array(
        'post_type' => 'page',
        'post_parent' => 7,
        'orderby' => 'title',
        'order' => 'ASC'
    );

    $query_brands = new WP_Query($args);

    while ($query_brands->have_posts()) : $query_brands->the_post(); 

        $id_brand = get_the_ID();
        $brand = get_post($id_brand, ARRAY_A);
        $slug_brand = $brand['post_name'];
        $titolo_brand = $brand['post_title'];

        $loop_brands[] = $slug_brand;

?>

        <p>
            <input type="checkbox" id="<?php echo $slug_brand; ?>" name="<?php echo $slug_brand; ?>" value="yes" <?php checked( get_post_meta($post->ID, $slug_brand, true ), 'yes' ); ?>>
            <label for="<?php echo $slug_brand; ?>"><?php echo $titolo_brand; ?></label>

        </p>

<?php endwhile;

}

function brands_add_meta_box() {

    add_meta_box(
        'brands-meta-box',
        'brands Meta Box',
        'brands_display_meta_box',
        'stores',
        'side',
        'high'
    );

}

add_action( 'add_meta_boxes', 'brands_add_meta_box' );

function brands_user_can_save( $post_id, $nonce ) {

    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ $nonce ] ) && wp_verify_nonce( $_POST[ $nonce ], plugin_basename( __FILE__ ) ) );

    return ! ( $is_autosave || $is_revision ) && $is_valid_nonce;

}

function brands_save_meta_box( $post_id ) {

    global $loop_brands;

    foreach ( $loop_brands as $brand ) {

        if ( brands_user_can_save( $post_id, $brand ) ) {

            if ( isset( $_POST[ $brand ] ) ) {

                update_post_meta( $post_id, $brand, $_POST[ $brand ]);

            } else {

                delete_post_meta( $post_id, $brand);

            }

        }

    }

}

add_action( 'save_post', 'brands_save_meta_box');
1
Alessio

Mon conseil serait d'extraire la partie requête de votre code:

function get_brands() {
  $loop_brands = array();

  wp_nonce_field( plugin_basename( __FILE__ ), 'brands-nonce-field' );

  $args = array(
      'post_type' => 'page',
      'post_parent' => 7,
      'orderby' => 'title',
      'order' => 'ASC'
  );

  $query_brands = new WP_Query($args);
  return $query_brands;
}

Ensuite, utilisez-le comme ceci:

function brands_save_meta_box( $post_id ) {
    $loop_brands = get_brands();
    $loop_brands = wp_list_pluck($loop_brands->posts,'post_name');
    foreach ( $loop_brands as $brand ) {
        if ( brands_user_can_save( $post_id, $brand ) ) {
            if ( isset( $_POST[ $brand ] ) ) {
                update_post_meta( $post_id, $brand, $_POST[ $brand ]);
            } else {
                delete_post_meta( $post_id, $brand);
            }
        }
    }
}

Ce serait la première étape. Sauf erreur de ma part, le code devrait fonctionner exactement comme avant, mais sans l'inquiétude et le désordre de la global.

Vous pouvez ensuite passer à une solution plus complexe comportant un peu de "mise en cache" si vous voulez:

function brands_query() {
  $loop_brands = array();

  wp_nonce_field( plugin_basename( __FILE__ ), 'brands-nonce-field' );

  $args = array(
      'post_type' => 'page',
      'post_parent' => 7,
      'orderby' => 'title',
      'order' => 'ASC'
  );

  $query_brands = new WP_Query($args);
  return $query_brands;
}

function get_brands() {
  $brands = get_option('loop_brands');
  if (empty($brands)) {
    $brands = brands_query();
    update_option('loop_brands',$brands);
  }
  return $brands;
}

Et si je le lis correctement, vous n’avez vraiment besoin que d’actualiser loop_brands sur la page enregistrer. Quelque chose comme ça:

function save_brands($post_id) {
  $brands = brands_query();
  update_option('loop_brands',$brands);
}
add_action('save_post_page','save_brands');
1
s_ha_dum

En gros, votre $loop_brands n'est pas reporté à la fonction de sauvegarde. Donc, vous exécutez foreach sur une variable vide/fausse, d’où l’erreur. Je suggère de sauvegarder le $loop_brands en tant que transitoire ou en tant qu’option. Ici, j'ai essayé un transitoire. Je ne pense pas que vous ayez besoin d'un moyen pour effacer le transitoire, car chaque fois que la métabox est chargée, le transitoire est actualisé. Il doit donc être à jour lors de l'exécution de la routine de sauvegarde. Je n'ai pas testé cela, donc votre kilométrage peut varier.

function brands_display_meta_box( $post ) { 

    wp_nonce_field( plugin_basename( __FILE__ ), 'brands-nonce-field' );

    $args = array(
        'post_type' => 'page',
        'post_parent' => 7,
        'orderby' => 'title',
        'order' => 'ASC'
    );

    $query_brands = new WP_Query($args);

    while ($query_brands->have_posts()) : $query_brands->the_post(); 

        $id_brand = get_the_ID();
        $brand = get_post($id_brand, ARRAY_A);
        $slug_brand = $brand['post_name'];
        $titolo_brand = $brand['post_title'];

        $loop_brands[] = $slug_brand;

?>

        <p>
            <input type="checkbox" id="<?php echo $slug_brand; ?>" name="<?php echo $slug_brand; ?>" value="yes" <?php checked( get_post_meta($post->ID, $slug_brand, true ), 'yes' ); ?>>
            <label for="<?php echo $slug_brand; ?>"><?php echo $titolo_brand; ?></label>

        </p>

<?php endwhile;

    set_transient( 'loop_brands', $loop_brands );

}

function brands_add_meta_box() {

    add_meta_box(
        'brands-meta-box',
        'brands Meta Box',
        'brands_display_meta_box',
        'stores',
        'side',
        'high'
    );

}

add_action( 'add_meta_boxes', 'brands_add_meta_box' );

function brands_user_can_save( $post_id, $nonce ) {

    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ $nonce ] ) && wp_verify_nonce( $_POST[ $nonce ], plugin_basename( __FILE__ ) ) );

    return ! ( $is_autosave || $is_revision ) && $is_valid_nonce;

}

function brands_save_meta_box( $post_id ) {

    $loop_brands = get_transient( 'loop_brands' );

    if( $loop_brands ):

    foreach ( $loop_brands as $brand ) {

        if ( brands_user_can_save( $post_id, $brand ) ) {

            if ( isset( $_POST[ $brand ] ) ) {

                update_post_meta( $post_id, $brand, $_POST[ $brand ]);

            } else {

                delete_post_meta( $post_id, $brand);

            }

        }

    }
    endif;

}

add_action( 'save_post', 'brands_save_meta_box');
1
helgatheviking