W jaki sposób przekazywać listy wielokrotnego wyboru z formularza do PHP?

Treść dodana: 10 lipca 2016.

W większości przypadków proste formularze HTML zawierają pojedyncze pola typu imię, nazwisko czy adres email. Odbiór danych po stronie PHP odbywa się za pomocą klucza w tablicy $_POST, który powiązany jest z atrybutem `name` formularza. Dla przykładu aby odebrać informację o płci danej osoby możemy wykorzystać następujący formularz:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Przykładowy formularz wyboru</title>
</head>
<body>
    <form class="test" action="" method="POST">
        <select name="plec">
            <option value="k">kobieta</option>
            <option value="m">mężczyzna</option>
        </select>
        <input type="submit" name="zapis" value="wyślij dane"/>
    </form>
</body>
</html>

Od strony PHP możemy podejrzeć wysłane dane wywołując polecenie

var_dump($_POST);
array(2) {
  ["plec"]=>
  string(1) "k"
  ["zapis"]=>
  string(12) "wyślij dane"
}

W wyniku otrzymamy 2-elementową tablicę. Klucz `plec` – $_POST[‘plec’] – odnosi się do elementu `select` i aktualnie wybranej opcji (w tym wypadku kobieta czyli indeks `k`). Klucz `zapis` $_POST[‘zapis’] – nawiązuje do elementu `input`. Warto pamiętać że również wszystkie elementy `submit` którym nadamy nazwy są odbierane przez PHP. Dzięki temu można np. rozróżnić który formularz został wysłany gdy mamy kilka na stronie.

Gdybyśmy chcieli teraz te proste dane zapisać do bazy należy bezwzględnie pamiętać o ich zabezpieczeniu.

// Wcześniej nawiązanie połączenia przez obiekt PDO oraz przygotowanie zapytania
$sth = $dbh->prepare($sql);
$sth->bindParam(1, $_POST['plec']);
$sth->execute();

Za pomocą formularza możemy wysyłać także listy wielokrotnego wyboru. Niech za przykład posłuży formularz do wyboru dnia tygodnia:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Przykładowy formularz wielokrotnego wyboru</title>
</head>
<body>
    <form class="test" action="" method="POST">
        <select name="dzien_tygodnia[]" multiple size=7>
            <option value="1">poniedziałek</option>
            <option value="2">wtorek</option>
            <option value="3">środa</option>
            <option value="4">czwartek</option>
            <option value="5">piątek</option>
            <option value="6">sobota</option>
            <option value="7">niedziela</option>
        </select>
        <input type="submit" name="zapis" value="wyślij dane"/>
    </form>
</body>
</html>

Co się zmieniło? Do pola `select` dodaliśmy atrybuty `multiple` oraz `size`. Atrybut multiple aktywował możliwość zaznaczania wielu opcji naraz (za pomocą klawiszy funkcyjnych `ctrl`, `shift`), atrybut size ograniczył widok listy do 7 elementów. Zaszła jeszcze jedna ważna zmiana. W nazwie pola `dzien_tygodnia` pojawiły się znaki [] które informują, że będziemy przesyłać tablicę wartości. Gdy teraz, zaznaczając wcześniej kilka wartości, wywołamy po stronie PHP funkcję var_dump($_POST) wynik będzie odmienny:

array(2) {
  ["dzien_tygodnia"]=>
  array(3) {
    [0]=>
    string(1) "2"
    [1]=>
    string(1) "4"
    [2]=>
    string(1) "5"
  }
  ["zapis"]=>
  string(12) "wyślij dane"
}

Dzień tygodnia nie jest (jak wcześniej płeć) stringiem, tylko kolejną automatycznie indeksowaną tablicą.

Aby teraz aktualizować rekordy w bazie danych na podstawie listy możemy wykorzystać konstrukcję SQL IN(). Problemem może być konieczność zabezpieczenia danych. Musimy wcześniej każdą wartość tablicy wybranych dni tygodnia podstawić do przygotowanego wcześniej `placeholdera`.

// sprawdzamy czy formularz został wysłany metodą POST i czy zawiera dane z przycisku submit
// pomijamy warunek jeżeli nie była wybrana żadna opcja
if ($_SERVER['REQUEST_METHOD'] === 'POST' && 
    isset($_POST['zapis']) && 
    !empty($_POST['dzien_tygodnia'])
    ) {
    // dodatkowe zabezpieczenie. Dane z formularza zawsze można zmienić 
    // lub wysłać inną metodą niż przez przeglądarkę

    // dni które użytkownik mógł przesłać przez formularz
    $mozliweDni = [1, 2, 3, 4, 5, 6, 7];
    // usuwamy dni nie występujące na liście możliwych dni
    $dostepneDni = array_filter($_POST['dzien_tygodnia'], function($a) use($mozliweDni) {
        return in_array($a, $mozliweDni);
    });
    if (empty($dostepneDni)) {
        return;
    }
    // przygotowujemy placeholder na podstawie dynamicznie obliczonej liczby elementów
    // dla 3 wybranych elementów będzie miał postać '?,?,?'
    $placeholder = implode(',', array_fill(0, count($dostepneDni), '?'));
    // przygotowujemy zapytanie
    // "UPDATE `table` SET `wartosc` = 5 WHERE `id` IN(?,?,?)" 
    $sql = 'UPDATE `table` SET `wartosc` = 5 WHERE `id` IN('. $placeholder .')';
    $sth = $dbh->prepare($sql);
    foreach ($dostepneDni as $k => $id) {
        // numeracja zaczyna się od 1 podczas gdy tablica $_POST zawiera indeksy od 0
        $sth->bindValue(($k+1), $id);
    }
    $sth->execute();
}

Komentarze

Nie ma jeszcze żadnych komentarzy do wyświetlenia. Może chcesz zostać pierwszą osobą która podzieli się swoją opinią?

Dodaj komentarz

*
Nazwa zostanie wyświetlona wraz z komentarzem. Możesz też utworzyć nowe konto w serwisie, dzięki czemu uzyskasz dodatkową funkcjonalność.
*
Akceptowana jest ograniczona składnia Textile. Wszystkie tagi HTML zostaną usunięte.