如何构建数组内含数组的Widget?

时间:2018-08-02 作者:S_E

我已经开始构建一个小部件,它需要在一个数组中包含一个数组。我正在尝试让小部件能够创建多个元素,这些元素将显示在站点上,但每个元素内部也有多个字段。。。但是,经过几天的搜索和尝试,我没有太多的运气把它整理出来。我希望有人能帮我纠正代码中的错误。它没有将字段数据保存到数据库中,因此我没有使用update命令正确查找值。如果我调整“$this->get_field_id(\'inner_elements\')“和”$this->get_field_name(\'inner_elements\')“在第一个$fields[\'icontxt\'] 元素并将“internal\\u elements”更改为“elements”,它确实会保存,但只保存最后一个数组元素的数据(到所有三个值,因为我还不知道如何在更新函数中指定它)。然而,如果我将这三个元素都从“inner\\u elements”更改为“elements”,则根本不起作用。在这段代码中,我只想显示3个字段,然后保存结果,但我计划在这起作用后构建一个下拉列表和其他控件(这样它们就不会都是相同的输入标记)。

据我猜测,我的大多数问题似乎都是在输入标签(在$字段内)中命名“id”和“name”的方式上,我需要在更新函数中专门保存它们。

// 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;
}
以下是我的大致思路:

enter image description here

该按钮将允许用户选择图像/图标,然后其他字段将是该图像/图标的附加值。单击加号将允许用户创建新的图像/图标(数组)和相关字段(内部数组)。

1 个回复
最合适的回答,由SO网友:nmr 整理而成

get_field_id 为字段id准备前缀,在一个小部件实例中总是相同的。表单字段可能类似于以下内容:

// -- $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">
您需要为每个字段使用不同的id/名称
此外,对字段组(txt、lnk和lnktrgt)进行编号,并将此编号添加到字段ID的末尾。单击“+”按钮后应执行相同操作。

$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">
不应$elements[$element_num] 在这里吗?您只留下一个索引。

$elements_num = count($elements);
$elements[$element_num + 1] = \'\';
<小时>Update
英寸update() 作用$new_instance 参数包含中使用的键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", 
]; 
从字段读取数据

//name= $this->get_field_name(\'icontxt\')" ...> 
<input class="widefat" id="..." name="" ...>  
内部update() 功能使用$value = $new_instance[\'icontxt\'][0];.

您可以尝试这样的代码将表单数据收集到数组中$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;

结束