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

Sergey1986,
вернувшись к "я не могу понять алгоритм и с чего начать". На картинке по ссылке в общем-то совсем иная задача выполняется, поэтому ставьте задачу конкретно ваших данных и что с ними нужно делать.

Пусть у вас данные, это имя и телефон. Вот на "телефон" нужно заострить внимание. Телефон в общем-то есть уникальное значение и при добавлении записи в базу сервер должен проверять уникальность номера, не допуская дубликатов номеров. Это можно возложить и на SQL, определив полю хранящему номер уникальный индекс. Но вопрос в том как он хранится в базе. А его можно хранить как строковое значение, например так 79999999999 или так +79999999999. Это один и тот же номер, но для SQL это будут два разных значения. Поэтому уникальный индекс не в помощь и придется разбираться иначе.

Все это к тому, что способ хранения номера может не позволить использовать поле его хранения как уникальный идентификатор записи в базе. Но в SQL существует механизм позволяющий автоматически создавать уникальный идентификатор для каждой записи, это поле с автоинкрементом и уникальным индексом являющееся первичным ключом. А полю хранящему номер определить простой индекс, он поможет в поиске по нему при проверке на уникальность номера при его добавлении.

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

Пусть такое поле создано в таблице и имеет имя id (Примечание: без большой необходимости не используйте в именах SQL таблиц разный регистр, для MySQL что FIO, что fio, что fiO, это одно и тоже, а вот путаницы и ошибок в РНР можно получить прилично, если не следить и не помнить об этом).

Встает вопрос как связать поля с идентификаторами их записей. РНР подготавливает данные формы как массив ее полей в суперглобальных массивах. А так как массив не может иметь двух одинаковых индексов и ключей, то именовать одноименные поля формы нужно с добавлением [], индексы РНР сам расставит, согласно порядку поля в форме. По этой же причине имя списка со множественным выбором нужно именовать также - name="name[]", иначе на сервере в массив попадут значения не всех опций выбранных в нем, а только значение последней, из выбранных, опции.

Если принудительно указывать индексы в именах полей, то можно управлять порядком элементов формы в полученном на сервере массиве. А если в качестве индексов указывать идентификаторы записей, то свяжем соответствующие поля формы с их записями в базе. При этом - такое именование позволит иметь на сервере практически любую нужную структуру массива. Например, если именовать поля так:

<input name="data[1][fio]" value="A" />
<input name="data[1][phone]" value="111" />
<input name="data[2][fio]" value="B" />
<input name="data[2][phone]" value="222" />
<input name="data[3][fio]" value="C" />
<input name="data[3][phone]" value="333" />


то на сервере получим массив:

Array
(
    [data] => Array
        (
            [1] => Array
                (
                    [fio] => A
                    [phone] => 111
                )

            [2] => Array
                (
                    [fio] => B
                    [phone] => 222
                )

            [3] => Array
                (
                    [fio] => C
                    [phone] => 333
                )
        )
)


где под каждым идентификатором записи (1, 2, 3) содержатся значения ее полей fio и phone. Вообще, необходимая структура массива зависит от того, что с данными предполагается делать. Показанная выше структура удобна при обновлении записей, а для вставки записей удобнее будет многомерный массив, вложения которого, это массивы fio и phone.

Если форма, которую вы получаете нужна для редактирования записей в базе (обновление/удаление), то кроме этих полей нужно иметь еще и поле определяющее то или иное действие. Вот тут и подошли к последнему вопросу - нужны ли куча кнопок submit в форме или нет? Если предполагается обновление/удаление по одной записи, то на каждую запись (каждые два поля в форме для каждой записи) необходимо иметь две кнопки submit, с именами, например "upd" и "del", а их значениями должны быть идентификаторы записей. Но значение кнопки submit, это текст на кнопке, поэтому использовать в этом случае нужно не type submit, а button - <button name="upd" value="1">Обновить</button> <button name="del" value="1">Удалить</button>. Полям fio и phone при этом не обязательно указывать идентификатор в имени. Клиентский сценарий должен получать соответствующие выбранной кнопке поля, отправляя их вместе с ней серверу.

Но можно над записями в базе производить и групповые операции, то есть как вам и хотелось - отправлять форму одной кнопкой. В этом случае сама кнопка на сервере не обязательно и нужна, то есть она может не иметь имени вообще. А для каждой группы полей формы, то есть каждой из записей, добавляется флажок с именем "del" и значением идентификатора записи в базе. Все выбранные флажки будут переданы серверу, сообщая какие записи нужно удалить, а какие обновить. И делается это на сервере "одним махом".

Можно писать код используя процедурный стиль даже для объектов, если это возможно. В mysqli возможны оба стиля, но хотя бы пробуйте объектный стиль, почему, понимание придет потом.

<?
//создаем объект
$dbo = new mysqli('host', 'user', 'pass', 'base_name');

//указываем поля нужные, если полей в таблице больше, и в нужном порядке
//так как мы свяжем поля с переменными для обработки результата запроса
//при этом имена полей таблицы в запросе могут не совпадать с именами переменных, в примере для поля fio
//поэтому и важен порядок полей в запросе
$sql = 'SELECT id, fio, phone FROM table ORDER BY id';

//подготавливаем запрос и проверяем
if($stmt = $dbo->prepare($sql)) {
    
    //выолняем запрос
    $stmt->execute();

    //связываем поля в запросе с переменными
    $stmt->bind_result($id, $name, $phone);
    
    echo '<form method="post">';
    //выводим форму, добавляя для полей флажок для удаления 
    while ($stmt->fetch()):?> 
        <input name="data[<?=$id?>][fio]" value="<?=$name?>" />
        <input name="data[<?=$id?>][phone]" value="<?=$phone?>" />
        <label><input type="checkbox" name="del[]" value="<?=$id?>" /> удалить</label>
    <?
    endwhile;
    echo '<button>Отправить</button><form>';
}
?>


По отправлению формы сервер получит массив data с ранее показанной структурой. Если будут выбраны флажки для удаления, то и массив del со значениями id записей, которые надо удалить. Далее простая операция по выявлению чего надо делать:

if($_POST['del']) {
    //если есть записи для удаления, вычтем их из массива обновлений
    $_POST['data'] = array_diff_key($_POST['data'], array_flip($_POST['del']));
    //делаем запрос для удаления
    $sql = 'DELETE FROM table WHERE id IN('.implode(','.$_POST['del']).')';
}

//если есть записи для обновления, обвновляем
if($_POST['data']) {
    //..... писать не буду, эту портянку пришлось писать частями в пост, ибо нет времени 
}


Все что здесь написано есть в руководстве, оно не сложно для понимания, нужно только изучать.

Примеры написаны без учета фильтрации данных, что вы обязаны делать, и не используются ? в подстановках в подготовленных запросах. Некогда это объяснять, читайте в руководстве.

Последний раз редактировалось laimas, 29.03.2018 в 02:53.
Ответить с цитированием