Поддержка Проблемы и решения Как верно сохранить в БД repeated-группу-полей?

  • Задача такая — создать мета-бокс, где содержится информация в нескольких текстовых полях, то есть группа полей, чтобы можно было производить неограниченное клонирование этой группы.

    Такая группа:
    val1: значение | val2: значение | val3: значение

    И её клонирование:
    val1: значение | val2: значение | val3: значение
    val1: значение | val2: значение | val3: значение
    val1: значение | val2: значение | val3: значение…

    У меня есть функция, которая позволяет мне делать клонирование одного поля и сохранять результат в базу данных, и получать на выходе массив. Вкратце, само поле в админке выводится так:

    $input = '
              <span class="item-personnel">
                <input type="text" name="'. self::$meta_key .'[]" value="%s">
                <span class="dashicons dashicons-trash remove-personnel-item"></span>
              </span>
              ';

    Нужно, чтобы оно выглядело примерно так:

    $input = '
      <span class="item-personnel">
        VAL1 <input type="text" name="'. self::$meta_key .'[val1]" value="%s">
        VAL2 <input type="text" name="'. self::$meta_key .'[val2]" value="%s">
        VAL3 <input type="text" name="'. self::$meta_key .'[val3]" value="%s">
      <span class="dashicons dashicons-trash remove-personnel-item"></span>
    </span>
    ';

    Я думаю, вся проблема просто в том, чтобы правильно сохранить значения мета-бокса. Сейчас сохранение происходит так:

     if ( wp_is_post_autosave( $post_id ) )
          return;
    
        if ( isset( $_POST[self::$meta_key] ) && is_array( $_POST[self::$meta_key] ) ) {
          $addresses = $_POST[self::$meta_key];
    
          $addresses = array_map( 'sanitize_text_field', $addresses );
    
          $addresses = array_filter( $addresses );
    
          if ( $addresses ) 
            update_post_meta( $post_id, self::$meta_key, $addresses );
          else 
            delete_post_meta( $post_id, self::$meta_key );
    
        }
      }

    Что нужно сделать, чтобы сохранить в массив несколько массивов (групп полей)?

    А вот вся моя функция целиком:

    new My_Custom_Fields;
    
    class My_Custom_Fields {
    
      public $post_type = 'page';
    
      static $meta_key = 'my_meta_key';
    
      public function __construct() {
        add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
        add_action( 'save_post_' . $this->post_type, array( $this, 'save_metabox' ) );
        add_action( 'admin_print_footer_scripts', array( $this, 'show_assets' ), 10, 999 );
      }
    
      public function add_metabox() {
        add_meta_box( 'my_meta_key_form', 'my_meta_key', array( $this, 'render_metabox' ), $this->post_type, 'advanced', 'high' );
      }
    
      public function render_metabox( $post ) {
    
        ?>
        <table class="form-table my_meta_key_form">
    
          <tr>
            <th>
              My Meta Box <span class="dashicons dashicons-plus-alt add-personnel"></span>
            </th>
            <td class="personnel-list">
              <?php
              $input = '
              <span class="item-personnel">
                <input type="text" name="'. self::$meta_key .'[]" value="%s">
                <span class="dashicons dashicons-trash remove-personnel-item"></span>
              </span>
              ';
    
              $addresses = get_post_meta( $post->ID, 'personnel', true );
    
              if ( is_array( $addresses ) ) {
                foreach ( $addresses as $addr ) {
                  printf( $input, esc_attr( $addr ) );
                }
              } else {
                printf( $input, '' );
              }
              ?>
            </td>
          </tr>
    
        </table>
    
        <?php
      }
    
      public function save_metabox( $post_id ) {
    
        if ( wp_is_post_autosave( $post_id ) )
          return;
    
        if ( isset( $_POST[self::$meta_key] ) && is_array( $_POST[self::$meta_key] ) ) {
          $addresses = $_POST[self::$meta_key];
    
          $addresses = array_map( 'sanitize_text_field', $addresses );
    
          $addresses = array_filter( $addresses );
    
          if ( $addresses ) 
            update_post_meta( $post_id, self::$meta_key, $addresses );
          else 
            delete_post_meta( $post_id, self::$meta_key );
    
        }
      }
    
      public function show_assets() {
        if ( is_admin() && get_current_screen()->id == $this->post_type ) {
          $this->show_styles();
          $this->show_scripts();
        }
      }
    
      public function show_styles() {
        ?>
        <style>
          .add-personnel {
            color: #00a0d2;
            cursor: pointer;
          }
          .personnel-list .item-personnel {
            display: flex;
            align-items: center;
          }
          .personnel-list .item-personnel input {
            width: 100%;
            max-width: 400px;
          }
          .remove-personnel-item {
            color: brown;
            cursor: pointer;
          }
        </style>
        <?php
      }
    
      public function show_scripts() {
        ?>
        <script>
          jQuery(document).ready(function ($) {
    
            var $companyInfo = $('.album-personnel');
    
            $('.add-personnel', $companyInfo).click(function () {
              var $list = $('.personnel-list');
                $item = $list.find('.item-personnel').first().clone();
    
              $item.find('input').val('');
    
              $list.append( $item );
            });
    
            $companyInfo.on('click', '.remove-personnel-item', function () {
              if ($('.item-personnel').length > 1) {
                $(this).closest('.item-personnel').remove();
              }
              else {
                $(this).closest('.item-personnel').find('input').val('');
              }
            });
    
          });
        </script>
        <?php
      }
    
    }