web-dev-qa-db-ja.com

配列内の配列でウィザードを構築する方法

配列の中に配列を持つ必要があるウィジェットを作り始めました。私はウィジェットにサイト上に表示される複数の要素を作成する能力を持たせようとしていますが、各要素の中に複数のフィールドもあります...しかし、数日の検索といろいろなことを試みた後、私はしていませんそれを整理してもらうことに多くの運がありました。誰かが私のコードのエラーを修正するのを手伝ってくれることを願っています。フィールドデータをデータベースに保存していないので、updateコマンドで値を正しく見つけることはできません。最初の$ fields ['icontxt']で "$ this-> get_field_id( 'inner_elements')"と "$ this-> get_field_name( 'inner_elements')"を調整した場合elementと "inner_elements"を "elements"に変更しても保存されますが、最後の配列要素のデータのみ(3つすべての値になります。ただし、3つすべてを "inner_elements"から "elements"に変更しても、まったく機能しません。このコードでは、3つのフィールドを表示してから保存します。しかし、これがうまくいったらドロップダウンリストと他のコントロールを作ることを計画しています(だからそれらはすべて同じinputタグにはなりません)。

私が推測できることから、私の問題の大部分は私が入力タグ($フィールドの内側)で "id"と "name"を命名している方法にあるようで、私はそれぞれupdate関数で保存する必要があります。

// 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 

ボタンは誰かが画像/アイコンを選択することを可能にします、そして他のフィールドはその画像/アイコンへの追加の値になります。プラス記号をクリックすると、ユーザーは新しい画像/アイコン(配列)と関連フィールド(内部配列)を作成できます。

4
S_E

get_field_idは1つのウィジェットインスタンス内でフィールド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]はここにはいけませんか? 1つのインデックスを残します。

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

アップデート
update()関数では、$new_instance parameresは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;
2
nmr