Показать сообщение отдельно
  #5 (permalink)  
Старый 26.09.2020, 22:51
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от l30
в php попадают значения только из первой строки, которая по дефолту появляется
Чего-то не то. Давайте так - данные уж точно будут писаться в базу, и такой переданный массив выгоднее писать в нее в пакетном режиме (многострочная вставка). Ограничения в таком режиме накладываются не на количество строк, а на их общий размер, и определяется sql-параметром max_allowed_packet. А учитывая то, что в базе каждая запись должна иметь свой уникальный идентификатор и формирование такового, это есть сам механизм SQL, а никак не нумерация клиентом, и записи в базу не только добавляются, но могут и удаляться из нее, наличие в ваших данных поля name="str[]", это нечто непонятное и никчемное.

То же самое можно сказать и о поле name="sum[]" - это какую же сумму нужно рассчитывать на клиенте, отправлять на север для сохранения в базе, если такие данные как количество и цена никогда не являлись величинами постоянными?

Я выбрасываю эти поля из данных, и все что нужно делать на клиенте, это:
- клонировать родительский узел
- найти в клоне поля и очистить их значения
- у кнопки удаления удалить класс remove, ибо этому классу по умолчанию указано быть невидимым, так как нельзя удалять из формы поля, если их набор в ней единственный
- вставить клон в родительский узел (в примере, это добавленный id="parent-box"), ему же делегируется и обработка кнопок удаления/добавления полей.

Как видите, если выполнить, отправив форму (добавлено для примера), то все добавленные наборы отправляются и ничего не пропадает.

<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
.remove {
    display: none;
}
</style>
<script type="text/javascript">
$(function() {
$('#parent-box').on('click', 'a', function(e) {
    e.preventDefault();
    
    var src = $(this), dst = src.closest('.row');
    
    if(src.hasClass('add')) {
        dst.clone()
           .find('input').val('')
           .end()
           .find('a').removeClass('remove')
           .end()
           .appendTo(e.delegateTarget)
    } else dst.remove();

});

$('form').submit(function(e) {
    e.preventDefault();
    alert(JSON.stringify($(this).serializeArray(), null, 4))
})    
});
</script>
</head>
<body>
<form>
<div id="parent-box">

  <div class="row">
    <div data-container="set">
    <div class="row p-2" data-item="set">
     <div class="col-4"> <input type="text"  name="name[]" value=""></div>
      <div class="col-1"> <input type="text"  name="num[]" value=""></div>
      <div class="col-2"> <input type="text"  name="price[]" value=""></div>
     
     <div class="col-2"> <a type="button" data-action="remove" class="remove">[-]</a>
      <a type="button" data-action="add" class="add">[+]</a>
     </div>
    </div>
  </div>
  </div>


</div>

<button>GO</button>
</form>
</body>
</html>


Но можно и "нумерацией" на клиенте заняться, но с совсем иной целью. Если на сервере при добавлении в базу используют ненумерованные метки, то пришедший массив данных:

Array
(
    [name] => Array
        (
            [0] => value
            [1] => value
            .....
        )

    [num] => Array
        (
            [0] => value
            [1] => value
            .....
        )

    [price] => Array
        (
            [0] => value
            [1] => value
            .....
        )
)


несложно преобразовать в массив для пакетной записи, как

$post = array_map(null, $_POST['name'], $_POST['num'], $_POST['price']);


получив массив:

Array
(
    [0] => Array
        (
            [0] => value
            [1] => value
            [2] => value
        )

    [1] => Array
        (
            [0] => value
            [1] => value
            [2] => value
        )
        .....
)


Но данные подлежат обязательной фильтрации, и производить ее с таким набором хоть и можно, но неудобно, а если работать с именованными метками (PDO), то такой набор не годится. Но можно именовать поля так (это у полей по умолчанию):

name="data[0][name]"
name="data[0][num]"
name="data[0][price]"

код добавления полей заменить на:

if(src.hasClass('add')) {
        var i = Date.now(); 
        dst.clone()
           .find('input').each(function() {
                this.value = '';
                this.name = this.name.replace(/\d+/, i) 
           })
           .end()
           .find('a').removeClass('remove')
           .end()
           .appendTo(e.delegateTarget)
    } else dst.remove();


то на сервере массив данных уже будет вот таким:

Array
(
    [data] => Array
        (
            [0] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )

            [1601149425635] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )

            [1601149432956] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )
             .....
        )
)


получаем $_POST['data'] для дальнейшей работы с данными, и эта структура выгоднее. Здесь метка времени используется как индекс вложенных массивов, что проще чем вычислять какой-то номер, а на сервере он не имеет никакого практического значения.

Последний раз редактировалось laimas, 27.09.2020 в 03:26.
Ответить с цитированием