¿Cómo almacenar datos de campos de widgets como una matriz?

11

Estoy creando un widget, necesita almacenar aproximadamente 10 ID. En este momento estoy usando el siguiente método de campo para almacenar cada una de las ID en un campo separado. Almacena datos de cada campo por separado en el wordpress. ¿Es posible almacenar los datos de todos los campos en una sola fila en WordPress para examinar usando una matriz?

<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']; ?>" 
    />
arrendajo
fuente
1
$instance es una matriz y contiene todos los valores. ¿Y qué quiere decir con "almacenar los datos de todos los campos en una sola fila"? ¿Quiso decir una fila de la base de datos?
Ralf912

Respuestas:

8

Tienes que recopilar múltiples campos con el mismo nombre como este ...

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

... y ajusta la lógica de tu widget a esto.

Aquí hay un widget de demostración muy 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

ingrese la descripción de la imagen aquí

Interfaz

ingrese la descripción de la imagen aquí

fuxia
fuente
+1 printfSintaxis muy elegante
Gran respuesta en múltiples campos, pero ¿es posible alguna actualización al tener 2 campos seguidos? Estoy tratando de usar esto en mi widget pero necesito tener 2 campos seguidos como precio / destino, pero no puedo encontrar la forma de obtenerlo, siempre recibo algún tipo de error.
Aleksandar Đorđević
@ AleksandarĐorđević Simplemente escriba el HTML para eso y no lo use class="widefat"para los campos.
fuxia
Si solo soy inteligente como piensas. Entiendo que se supone que debo guardarlo en la base de datos como campo [0] [precio] y campo [0] [destino] y así sucesivamente. pero de alguna manera no lo hago bien.
Aleksandar Đorđević
¿Es posible ser una matriz que tenga pares clave / valor?
worldwildwebdev
5

La respuesta anterior es buena si necesita que los campos estén numerados. En mi caso, no lo hice. Tengo un widget con opciones que permiten al usuario seleccionar cualquier número de categorías para usar dentro del widget.

widget

Aquí está mi widget form. - Tres cosas importantes aquí

  1. Asegúrese de predeterminar el valor a vacío array()si el valor del widget no está establecido
  2. En el <label> nameatributo de formulario , observe que adjunto un []al final. Esto le dice a PHP que estoy enviando una matriz de valores para esta clave
  3. Envuelva la casilla de verificación en la etiqueta como <label><input type="checkbox" ...></label>. - Cada una de nuestras casillas de verificación no tendrá un idatributo único , por lo que el <label> foratributo no funcionará. Podríamos generar ID únicos, pero eso es una molestia. Si solo ajusta la etiqueta alrededor de la entrada, la etiqueta se asociará correctamente sin la molestia de conectar el for+id

Ahora el código

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
}

Y aquí está mi función de actualización

Estoy interesado en guardar la identificación categoría en una matriz, que son los números, así que uso array_mapcon intvalpara asegurar que todo dato presentado son números enteros válidos. Además, uso array_filterpara eliminar cualquier envío no válido.

// @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']
  );
}

Es particularmente desafiante describir estas cosas de WordPress. Si tiene alguna pregunta, estaré encantado de elaborarla.


fuente