Como construir widget com matrizes dentro de matrizes?

4

Eu comecei a criar um widget que precisa ter uma matriz dentro de uma matriz. Eu estou tentando fazer com que o widget tenha a capacidade de criar vários elementos que serão exibidos no site, mas também tem vários campos dentro de cada elemento ... mas depois de alguns dias pesquisando e tentando várias coisas, eu não tenho teve muita sorte em resolver isso. Espero que alguém possa ajudar a corrigir os erros no meu código aqui. Não está salvando os dados de campo no banco de dados, portanto, não tenho o comando update localizando os valores corretamente. Se eu ajustar " $ this- > get_field_id ('inner_elements') " e " $ this- > get_field_name ('inner_elements') " no primeiro $ fields ['icontxt'] e altere " inner_elements elementos ", ele salva, mas apenas os dados do último elemento da matriz ( para todos os três valores, desde que eu não descobri como especificá-lo na função de atualização). No entanto, se eu mudar todos os três de "inner_elements" para "elementos", não funciona de todo. Neste código, estou apenas tentando exibir três campos e, em seguida, salve os resultados, mas planejo criar em uma lista suspensa e outros controles, uma vez que isso esteja funcionando (para que eles não sejam todos a mesma tag de entrada).

Pelo que eu posso imaginar, parece que a maioria dos meus problemas estão na maneira como estou nomeando o "id" e "name" nas tags de entrada (dentro de $ fields) e preciso salvar cada um especificamente no função de atualização.

// Widget Backend 
public function form( $instance ) {
$title = isset ($instance['title']) ? $instance['title'] : 'New Title';

$elements = isset ($instance['elements']) ? $instance['elements'] : array();
$elements_num = count($elements);
$elements[$element_num + 1] = '';
$elements_counter = 0;
$inner_elements_counter = 0;

foreach($elements as $element){
    $inner_elements = isset($instance['elements']['inner_elements']) ? $instance['elements']['inner_elements'] : array(
        'icontxt' => 'The Icon Text',
        'iconlnk' => 'The Icon Link',
        'iconlnktrgt' => 'Link Target'
    );
    $fields = array();

    $fields['icontxt'] = sprintf(
        '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
        $this->get_field_id('inner_elements'),
        $this->get_field_name('inner_elements'),
        $elements_counter,
        esc_attr($inner_elements['icontxt'])
    );
    $fields['iconlnk'] = sprintf(
        '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
        $this->get_field_id('inner_elements'),
        $this->get_field_name('inner_elements'),
        $elements_counter,
        esc_attr($inner_elements['iconlnk'])
    );
    $fields['iconlnktrgt'] = sprintf(
        '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
        $this->get_field_id('inner_elements'),
        $this->get_field_name('inner_elements'),
        $elements_counter,
        esc_attr($inner_elements['iconlnktrgt'])
    );

    $elements_counter += 1;
}

//displays the widget in admin
print 'Elements<br />' . join('<br />', $fields);
}

// Updating widget replacing old instances with new
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = esc_html($new_instance['title']);
$instance['elements'] = array();
$instance['elements']['inner_elements'] = array();
if(isset($new_instance['elements'])){
    foreach($new_instance['elements'] as $element){
        if('' !== trim($element)){
            //$instance['inner_elements'] = array();
            foreach($new_instance['inner_elements'] as $inner_element){
                //$instance['elements']['inner_elements'][] = $inner_element;
                $instance['elements']['inner_elements']['icontxt'] = $inner_element;
                $instance['elements']['inner_elements']['iconlnk'] = $inner_element;
                $instance['elements']['inner_elements']['iconlnktrgt'] = $inner_element;
            }
        }
    }
}
return $instance;
}

Aqui está uma ideia geral de para onde estou indo:

O botão permitirá que alguém selecione uma imagem / ícone e, em seguida, os outros campos serão valores adicionais a essa imagem / ícone. Clicar no sinal de mais permitirá ao usuário criar uma nova imagem / ícone (matriz) e campos relacionados (matriz interna).

    
por S_E 02.08.2018 / 20:51

1 resposta

2

get_field_id prepare o prefixo para o id do campo, em uma instância do widget é sempre o mesmo. Seus campos de formulário provavelmente são semelhantes a estes:

// -- $element[0] --
  // $field[icontxt]
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][0]" value="%4$s">
  // $field[iconlnk]
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][0]" value="%4$s">
  //$field[iconlnktrgt]
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][0]" value="%4$s">

// -- $element[1] --
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][1]" value="%4$s">
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][1]" value="%4$s">
<input class="widefat" id="widget-baseid-instance-inner_elements" name="widget-baseid[instance][inner_elements][1]" value="%4$s">

Você precisa usar id / nome diferente para cada campo.
Além disso, numere o grupo de campos (txt, lnk e lnktrgt) e adicione esse número ao final do ID do campo. O mesmo deve ser feito depois de clicar no botão "+".

$fields['icontxt'] = sprintf(
    '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
    $this->get_field_id('icontxt' . $elements_counter),
    $this->get_field_name('icontxt'),
    $elements_counter,
    esc_attr($inner_elements['icontxt'])
);
$fields['iconlnk'] = sprintf(
    '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
    $this->get_field_id('iconlnk' . $elements_counter),
    $this->get_field_name('iconlnk'),
    $elements_counter,
    esc_attr($inner_elements['iconlnk'])
);
$fields['iconlnktrgt'] = sprintf(
    '<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
    $this->get_field_id('iconlnktrgt' . $elements_counter),
    $this->get_field_name('iconlnktrgt'),
    $elements_counter,
    esc_attr($inner_elements['iconlnktrgt'])
);

<input class="widefat" id="widget-baseid-instance-icontxt0" name="widget-baseid[instance][icontxt][0]" value="%4$s">
<input class="widefat" id="widget-baseid-instance-iconlnk0" name="widget-baseid[instance][iconlnk][0]" value="%4$s">
<input class="widefat" id="widget-baseid-instance-iconlnktrgt0" name="widget-baseid[instance][iconlnktrgt][0]" value="%4$s">

Não deve $elements[$element_num] estar aqui? Você deixa um índice.

$elements_num = count($elements);
$elements[$element_num + 1] = '';

Atualizar
Na função update() , $new_instance parameres contém as chaves usadas em form() - 'icontxt', 'iconlnk', 'iconlnktrgt':

$new_instance[icontxt][ 
      0 => "some value from field no. 1", 
      1 => "value from field no. 2", 
];
$new_instance[iconlnk][ 
      0 => "link from first field ", 
      1 => "second link", 
]; 

Para ler dados do campo

//name= $this->get_field_name('icontxt')" ...> 
<input class="widefat" id="..." name="" ...>  

dentro da função update() use $value = $new_instance['icontxt'][0]; .

Você pode tentar um código como este para coletar dados de formulário no array $elements['inner_elements'] :

// arrays initialization
$tmp_elements = [ 'inner_elements' => [] ];
if ( isset($new_instance['icontxt']) ) {
    for($i = 0; $i < count( $new_instance['icontxt'] ); ++$i)
        $tmp_elements['inner_elements' . $i]['icontxt'] = $new_instance['icontxt'][$i];
    unset($new_instance['icontxt']);
}
// ...
$new_instance['elements'] = $tmp_elements;
    
por nmr 02.08.2018 / 23:47

Tags