Comment stocker les données des champs de widget sous forme de tableau?

11

Je crée un widget, il doit stocker environ 10 identifiants. En ce moment, j'utilise la méthode de champ suivante pour stocker chacun de l'ID dans un champ distinct. Il stocke les données de chaque champ dans un séparément dans le wordpress. Est-il possible de stocker les données de tous les champs dans une seule ligne dans wordpress pour examen à l'aide d'un tableau?

<input 
    class="widefat" 
    id="<?php echo $this->get_field_id('item1_id'); ?>" 
    name="<?php echo $this->get_field_name('item1_id'); ?>" 
    value="<?php echo $instance['item1_id']; ?>" 
    />

<input 
    class="widefat" 
    id="<?php echo $this->get_field_id('item2_id'); ?>" 
    name="<?php echo $this->get_field_name('item2_id'); ?>" 
    value="<?php echo $instance['item2_id']; ?>" 
    />
geai
la source
1
$instance est un tableau et contient toutes les valeurs. Et que voulez-vous dire par «stocker les données de tous les champs sur une seule ligne»? Voulez-vous dire une ligne de base de données?
Ralf912

Réponses:

8

Vous devez collecter plusieurs champs sous le même nom comme celui-ci…

name="collect[1]"
name="collect[2]"

… Et ajustez la logique de votre widget à cela.

Voici un widget de démonstration très simple:

<?php  # -*- coding: utf-8 -*-
/* Plugin Name: Store Options as array */

add_action( 'widgets_init', array ( 'T5_Array_Options_Widget', 'register' ) );

class T5_Array_Options_Widget extends WP_Widget
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct( strtolower( __CLASS__ ), 'Array Demo' );
    }

    /**
     * Echo the settings update form
     *
     * @param array $instance Current settings
     */
    public function form( $instance )
    {
        $title = isset ( $instance['title'] ) ? $instance['title'] : '';
        $title = esc_attr( $title );

        printf(
            '<p><label for="%1$s">%2$s</label><br />
            <input type="text" name="%3$s" id="%1$s" value="%4$s" class="widefat"></p>',
            $this->get_field_id( 'title' ),
            'Title',
            $this->get_field_name( 'title' ),
            $title
        );

        $fields = isset ( $instance['fields'] ) ? $instance['fields'] : array();
        $field_num = count( $fields );
        $fields[ $field_num + 1 ] = '';
        $fields_html = array();
        $fields_counter = 0;

        foreach ( $fields as $name => $value )
        {
            $fields_html[] = sprintf(
                '<input type="text" name="%1$s[%2$s]" value="%3$s" class="widefat">',
                $this->get_field_name( 'fields' ),
                $fields_counter,
                esc_attr( $value )
            );
            $fields_counter += 1;
        }

        print 'Fields<br />' . join( '<br />', $fields_html );
    }

    /**
     * Renders the output.
     *
     * @see WP_Widget::widget()
     */
    public function widget( $args, $instance )
    {
        print $args['before_widget']
        . $args['before_title']
        . apply_filters( 'widget_title', $instance['title'] )
        . $args['after_title']
        . join( '<br />', $instance['fields'] )
        . $args['after_widget'];
    }

    /**
     * Prepares the content. Not.
     *
     * @param  array $new_instance New content
     * @param  array $old_instance Old content
     * @return array New content
     */
    public function update( $new_instance, $old_instance )
    {
        $instance          = $old_instance;
        $instance['title'] = esc_html( $new_instance['title'] );

        $instance['fields'] = array();

        if ( isset ( $new_instance['fields'] ) )
        {
            foreach ( $new_instance['fields'] as $value )
            {
                if ( '' !== trim( $value ) )
                    $instance['fields'][] = $value;
            }
        }

        return $instance;
    }

    /**
     * Tell WP we want to use this widget.
     *
     * @wp-hook widgets_init
     * @return void
     */
    public static function register()
    {
        register_widget( __CLASS__ );
    }
}

Backend

entrez la description de l'image ici

L'extrémité avant

entrez la description de l'image ici

fuxia
la source
+1 printfSyntaxe très élégante
Excellente réponse sur plusieurs champs, mais est-il possible de mettre à jour le fait d'avoir 2 champs d'affilée? j'essaie de l'utiliser sur mon widget mais j'ai besoin d'avoir 2 champs d'affilée comme le prix / destination, mais je ne peux pas comprendre comment l'obtenir, je reçois toujours une sorte d'erreur.
Aleksandar Đorđević
@ AleksandarĐorđević Il suffit d'écrire le code HTML pour cela et de ne pas l'utiliser class="widefat"pour les champs.
fuxia
Si je suis juste intelligent comme vous le pensez. Je comprends que je suis censé le faire enregistrer dans la base de données en tant que champ [0] [prix] et champ [0] [destination] et ainsi de suite? mais d'une manière ou d'une autre je ne le fais pas bien.
Aleksandar Đorđević
Est-il possible que foo soit un tableau ayant des paires clé / valeur?
worldwildwebdev
5

La réponse ci-dessus est bonne si vous avez besoin que les champs soient numérotés. Dans mon cas, je ne l'ai pas fait. J'ai un widget avec des options qui permettent à l'utilisateur de sélectionner n'importe quel nombre de catégories à utiliser dans le widget.

widget

Voici mon widget form. - Trois choses importantes ici

  1. Assurez-vous que la valeur par défaut est vide array()si la valeur du widget n'est pas définie
  2. Dans l' <label> nameattribut de formulaire , notez que j'attache un []à la fin. Cela indique à PHP que je soumets un tableau de valeurs pour cette clé
  3. Enveloppez la case à cocher dans l'étiquette comme <label><input type="checkbox" ...></label>. - Chacune de nos cases à cocher n'aura pas d' idattribut unique , donc l' <label> forattribut ne fonctionnera pas. Nous pourrions générer des identifiants uniques, mais c'est un problème. Si vous enveloppez simplement l'étiquette autour de l'entrée, l'étiquette est correctement associée sans les tracas de connexion du for+id

Maintenant, le code

public function form($instance) {
  $title = isset($instance['title']) ? $instance['title'] : '';
  $categories = isset($instance['categories']) ? $instance['categories'] : array();
  ?>

  <p>
    <label for="<?php echo $this->get_field_id('title') ?>">
      <?php _e( 'Title:' ) ?>
    </label>
    <input class="widefat"
           id="<?php echo $this->get_field_id('title') ?>"
           name="<?php echo $this->get_field_name('title') ?>"
           value="<?php echo $title ?>" />
  </p>

  <p>Categories</p>
  <ul>
  <?php foreach (\get_categories() as $category): ?>
    <li>
      <label>
        <input type="checkbox"
             class="checkbox"
             name="<?php echo $this->get_field_name('categories') ?>[]"
             value="<?php echo $category->cat_ID ?>"
             <?php checked(in_array($category->cat_ID, $categories)) ?> />
        <?php echo $category->name ?>
      </label>
    </li>
  <?php endforeach ?>
  </ul>
  <?php
}

Et voici ma fonction de mise à jour

Je souhaite enregistrer les identifiants de catégorie dans un tableau, qui sont des nombres, donc j'utilise array_mapavec intvalpour m'assurer que toutes les données soumises sont des entiers valides. De plus, j'utilise array_filterpour supprimer toutes les soumissions invalides.

// @param array $a - the new instance options
// @param arram $b - the old instance options
public function update($a, $b) {
  return array(
    'title'      => isset($a['title']) ? strip_tags($a['title']) : $b['title'],
    'categories' => isset($a['categories']) ? array_filter(array_map(function($id) { return intval($id); }, (array) $a['categories'])) : (array) $b['title']
  );
}

Il est particulièrement difficile de décrire ce truc WordPress. Si vous avez des questions, je me ferai un plaisir de vous en dire plus.


la source