Je checkbox zaškrtnutý, alebo nezaškrtnutý?

pmasarik | Štvrtok 11. 01. 2007, 06.15 | PHP

Urobil som update článku lebo som nebol pochopený prečo riešim tento problém.

<-? tu je originál článok ?->
Hodnoty s formulárových checkboxov sa spracovávajú v PHP jednoducho, ale čo ak máme napríklad týchto checkboxov viac a potrebujeme zistiť ktorý je zaškrtnutý a ktorý je nezaškrtnutý.

Problém je v tom, že ak nie je checkbox zaškrtnutý, jeho hodnota sa na server vôbec nezasiela.

// pri zaškrtnutom checkboxe sa odošle hodnota 1
// pri nezaškrtnutom sa nic neodošle
<input type="checkbox" name="nazov[]" value="1">

Ak hodnoty len zadávame, tak to nie je problém, ale ak chceme odškrtnutím checkboxu a zaslaním formulára nejakú vlastnosť zrušiť, tak nedokážeme zistiť ktorý checkbox je nezaškrtnutý.

Riešenie problému

Riešenie problému je pomerne jednoduché, stačí pridať ku každému chceckboxu jeden skrytý input, ktorý bude mať rovnaké meno ako checkbox. Tento skrytý input sa bude zasielať vždy a ak bude checkbox nezaškrtnutý tak spracujeme hodnotu z tohoto skrytého inputu.

// v prípade že bude checkbox zaškrtnutý hodnota bude 1
// ak bude checkbox nezaškrtnutý bude hodnota 0, lebo hodnota 1 sa na server neodošle
<input type="hidden" name="nazov[]" value="0">
<input type="checkbox" name="nazov[]" value="1">

Možno sa to dá vyriešiť aj nejako elegantnejšie, takže ak niekto pozná lepšie riešenie tak nech mi dá vedieť v komentároch.

<-? tu je koniec originál článku ?->


Nové vysvetlenie problému

Ako som písal problém nie je pri spracovaní, ale pri následnej editácii. Vysvetlenie na konkrétnom príklade bude najrozumnejšie. Na tejto stránke je príklad kde máme 5ks inputov typu checkbox.

Po ich odoslaní sa nám zobrazí pole kde vidíme aké údaje sa nám odoslali na server. Ak odškrtneme niektoré zaškrtnuté políčko tak zistíme že táto hodnota sa nám neodoslala a následne nemáme odkiaľ vedieť čo máme zmeniť.

HTML časť toho súboru si môžete pozrieť a PHP časť je takáto:

if (isset($_POST['ID'])) {
 echo '<pre>';
 print_r($_POST['ID']);
 echo '</pre>';
}

Z tohoto dôvodu som začal hľadať nejaké riešenie, ako zistiť ktorý checkbox bol odškrtnutý.

Riešenie rovnakého NAME

Ako správne dusoft poznamenal rovnaké NAME nie je povolené a preto som trochu pozmenil riešenie.

<input type="hidden" name="nazov_hidden[]" value="1">
<input type="checkbox" name="nazov[]" value="1">

Následne to skontrolujeme a vyhodnotíme v PHP:

foreach ($_POST["nazov_hidden"] as $key => $value) {
    if ($_POST["nazov"][$key] == $value) {
        // ak 1 = 1 checkbox bol zaškrtnutý
    } else {
       // nebol zaškrtnutý
    }
}

Dúfam že tento raz som to vysvetlil lepšie a každý pochopí v čom vidím problém :-(


Páči sa vám tento článok, zalinkujte ho:

««« Predchádzajúci text: Prison Break, najlepší seriál na svete Následujúcí text: Lightbox plus »»»

Verzia pre tlač | 20 komentárov | 1665x

Komentáre k textu

Rss komentářů tohoto textu - Formulár pre nový komentár

1
reaguj[1] web dusoft nie je zle riesenie

je mozne mat v XHTML dva rozne elementy s rovnakym nazvom (s ID urcite nie).

ak mame hodnoty v DB, tak vieme priklad riesit jednoduchsie – ak hodnota checkboxu nebola odoslana, tak pri jej porovnani s DB odlozime nabok a nasledne zmazeme/vypneme alebo podobne.

Štvrtok 11. 01. 2007, 09.16
2
reaguj[2] web dusoft unikatnost nazvov name / ID

Further, since the set of legal values for attributes of type ID is much smaller than for those of type CDATA, the type of the name attribute has been changed to NMTOKEN. This attribute is constrained such that it can only have the same values as type ID, or as the Name production in XML 1.0 Section 2.3, production 5. Unfortunately, this constraint cannot be expressed in the XHTML 1.0 DTDs. Because of this change, care must be taken when converting existing HTML documents. The values of these attributes must be unique within the document, valid, and any references to these fragment identifiers (both internal and external) must be updated should the values be changed during conversion.

Štvrtok 11. 01. 2007, 09.18
3
reaguj[3] web johno

dusoft napsal/a: ak mame hodnoty v DB, tak vieme priklad riesit jednoduchsie – ak hodnota checkboxu nebola odoslana, tak pri jej porovnani s DB odlozime nabok a nasledne zmazeme/vypneme alebo podobne

Skús si toto:

<input type="checkbox" name="nazov[]" />
<input type="checkbox" name="nazov[]" />
<input type="checkbox" name="nazov[]" />

A potom zisti, ktorý checkbox som zaškrtol. Nemáš šancu.

Keďže si však správne podotkol, že väčšinou majú tie hodnoty aj nejaké id v DB, takže najjednoduchšie asi takto:

<input type="checkbox" name="nazov[1]" />
<input type="checkbox" name="nazov[2]" />
<input type="checkbox" name="nazov[3]" />
Štvrtok 11. 01. 2007, 09.34
4
reaguj[4] web tiso

[3] johno : keď tam pridáš value tak nie je problém…

Štvrtok 11. 01. 2007, 09.49
5
reaguj[5] web johno

tiso napsal/a: keď tam pridáš value tak nie je problém…

No áno, ale potom sme presne tam, kde pmasarik začal, nie? To, že som nepochopil, kde s tým má problém pmasarik, je vec druhá.

Štvrtok 11. 01. 2007, 09.59
6
reaguj[6] web dusoft nemusi byt value

staci dat ID do pola nazov[$ID]

Štvrtok 11. 01. 2007, 14.01
7
reaguj[7] web pmasarik update

Reakcie v upravenom článku… 8-)

Štvrtok 11. 01. 2007, 22.16
8
reaguj[8] web tiso

[7] pmasarik : takto som to myslel:

<?php
if(isset($_POST["sub"])){
        if (isset($_POST['ID'])) {
                echo '<pre>';
                print_r($_POST['ID']);
                echo '</pre>';
        }
}
?>
<form action="" method="post">
<p>ID1<input type="checkbox" name="ID[]" value="1" checked /></p>
<p>ID2<input type="checkbox" name="ID[]" value="2" checked /></p>
<p>ID3<input type="checkbox" name="ID[]" value="3" /></p>
<p>ID4<input type="checkbox" name="ID[]" value="4" /></p>
<p>ID5<input type="checkbox" name="ID[]" value="5" checked /></p>
<p><input type="submit" name="sub" value="submit" /></p>
</form>

ak nie tak prečo?

Piatok 12. 01. 2007, 00.39
9
reaguj[9] web pmasarik

[8] tiso : možno hľadám problém tam kde nie je a riešenie je jednoduché, ale ja stále nechápem, ako zistíš ktorý checkbox som odšrtol.

Tvoje riešenie som dal sem http://www.pmasarik.info/…x/index2.php

Ak odškrtneš napr. ID2 a ID5 tak sa ti odošle len toto:

Array
(
    [0] => 1
)

To že tam nie je 2 a 5 sa nedá podľa mňa jednoznačne vyhodnotiť že som niečo odškrtol. Môže nastať situácia, že tých checkboxov bude 100 a nebudú mať ID postupne od 1 po 100, lebo sa medzi časom zmazali niektoré záznamy z databáze. Ako budeš zisťovať ktorému záznamu urobiť UPDATE a ktorému nie? Toto mi prosím niekto vysvetlite, že či si sedím na kábli, alebo mám pravdu 8-O

Piatok 12. 01. 2007, 06.50
10
reaguj[10] web johno

pmasarik napsal/a: Môže nastať situácia, že tých checkboxov bude 100 a nebudú mať ID postupne od 1 po 100, lebo sa medzi časom zmazali niektoré záznamy z databáze

No tak toto by sa podľa mňa reálne stať nemalo. A aj keby. Prečo by ťa malo zajímať, že to niekto odškrtol, keď je tá položka aj tak medzičasom zmazaná. Nejako mi unikajú súvislosti.

Piatok 12. 01. 2007, 08.40
11
reaguj[11] web pmasarik

[10] johno : OK zase som sa asi zle vyjadril. Záznamy sa nevymažú počas procesu spracovania.

Príklad: máme nasledovnú DB

CREATE TABLE `produkt` (
  `produkt_id` int(11) NOT NULL auto_increment,
  `akcia` tinyint(1) unsigned NOT NULL default '0',
  PRIMARY KEY  (`produkt_id`)
) ENGINE=MyISAM ;

INSERT INTO `produkt` (`produkt_id`, `akcia`) VALUES
(1, 0), (2, 1), (4, 1), (8, 0), (9, 1), (10, 1), (11, 0), (15, 1), (18, 1);

Zámerne som nedal produkt_id postupne, lebo mazanie riadkov je bežná vec a takto nám vznikne to že nemáme čísla v postupnosti.

Z tejto DB vygenerujeme checkbox inputy, kde NAME bude obsahovať ID produkt_id.

Ak sa mi po odoslaní formulára odošlú len tie hodnoty ktoré boli zaškrtnuté, odkiaľ zistím ktoré niekto odškrtol?

Akým systémom to mám podľa teba spracovať, aby som zistil ktoré produkt_id mali hodnotu akcia = 1 a následne ju zmeniť na 0?

Piatok 12. 01. 2007, 14.35
12
reaguj[12] web tiso

[11] pmasarik : aha…

  1. formulár spravíš tak že do value každého inputu dáš produkt_id, a keď máš akcia=1 tak i atribút chcecked
  2. po odoslani si dáš dokopy id-cka aby ti pasovali do dotazu (1, 2, 5)
  3. dotaz, napríklad: UPDATE product… WHERE (akcia=‚1‘) AND (product_id NOT IN(1, 2, 5))

Je problém že musíš rozlíšiť 2 stavy – tie čo boli 1 a chceš ich na 0 a tie čo boli 0 a chceš ich na 1, čo je na 2 dotazy, neviem či to ide jedným…

Piatok 12. 01. 2007, 16.04
13
reaguj[13] web pmasarik Asi som pako, ale ja to furt nechápem

tiso napísal: po odoslani si dáš dokopy id-cka aby ti pasovali do dotazu (1, 2, 5) no a povedz mi ako si ich dám dokopy, keď sa mi neodoslali práve tie ktoré potrebujem zmeniť?

Ešte raz príklad.

Takže v DB máme napríklad toto:

  • ID1 = 1
  • ID2 = 1
  • ID3 = 0
  • ID4 = 0
  • ID5 = 1

s toho vygenerujem toto:

<input type="checkbox" name="ID[1]" value="1" checked />
<input type="checkbox" name="ID[2]" value="1" checked />
<input type="checkbox" name="ID[3]" value="1" />
<input type="checkbox" name="ID[4]" value="1" />
<input type="checkbox" name="ID[5]" value="1" checked />

odškrtneme name[ID1] a name[ID5]
odošlem formulár a potrebujeme to updatnut na toto:

  • ID1 = 0
  • ID2 = 1
  • ID3 = 0
  • ID4 = 0
  • ID5 = 0

lenže sa mi odošle len toto:

ID2 = 1

Ako podľa tejto jednej hodnoty zistím čo sa má zmeniť v DB???

Piatok 12. 01. 2007, 16.31
14
reaguj[14] web tiso

[13] pmasarik : odpoveď na Tvoj príklad: NIJAKO… Preto som Ti napísal tie 3 body – ako vytvoriť formulár, ako ho spracovať a návod na dotaz… k bodu 2: (1, 2, 5) je tvar v akom to máš dostať… Keď odznačíš 2 a 5 tak z toho zostane len NOT IN (1)… Chápeme sa?

Piatok 12. 01. 2007, 19.51
15
reaguj[15] web pmasarik

[14] tiso : OK už sa chápeme, ale mám zase ďalší problém.

Čo ak je v DB viac záznamov a ja potrebujem editovať len niektoré a následne ich spracovať.
Tým dotazom totiž prepíšem aj tie hodnoty ktoré nepotrebujem editovať.

Mne išlo o nejaké univerzálnejšie riešenie kde na začiatku neviem čo editujem, ale po editácii budem na 100% vedieť výsledok čo sa ako zmenilo.
Lebo ak popredu viem čo editujem tak sa to dá urobiť inými určite jednoduchšími spôsobmi.

Piatok 12. 01. 2007, 20.17
16
reaguj[16] web johno

No už to chápem. Takže teraz si myslím, že s najväčšou pravdepodobnosťou riešiš nepodstatnú blbosť a na nejaké žmýkanie výkonu sa treba vykašlať a robiť veci hlavne jednoducho. Takže dve možnosti:

  1. Update všetkých na 0 a potom update všetkých zaškrtnutých na 1.
  2. Zmazať všetko a insert zašktnutých. To len ak je to čisto prepojovacia tabuľka a teda value object.
Piatok 12. 01. 2007, 20.18
17
reaguj[17] web tiso

[15] pmasarik : takže stránkovanie – myslím že doplniť podmienku pre „stránku“ nie je problém…

[16] johno : 1. to mi nenapadlo, dobrý nápad…

Piatok 12. 01. 2007, 21.26
18
reaguj[18] K.Feldsam

[12] tiso: Zdravim, ako si ich mam dat do kopy, a nerozumiem tomu not in. viete sem hodit php kod? ak som pochopil spravne tak form ma vypadat takto

<input type="checkbox" name="netusim" value="product_id" />

name hodnota ma byt rovnaka alebo vzdy ina? lebo ak rovnaka tak si uz vobec neviem predstavit ako to spracovat. dikes za odpoved.

Štvrtok 27. 12. 2007, 17.38
19
reaguj[19] K.Feldsam

Už som to vzmzslel po svojom:

<h4>Oprávnenia uľívateµov</h4>
<?
if(isset($_GET[action])){
$datax=Array();
$datax=$_POST;
for($xx=1; $xx < 100; $xx++){
if($datax[$xx] != ''){
$update = mysql_query("UPDATE users SET laws='$datax[$xx]' WHERE uid='$xx'");}
}
}

Takto vyzerá moj zdroják…

Štvrtok 27. 12. 2007, 20.04
20
reaguj[20] K.Feldsam
$sql = mysql_query("SELECT uid,meno,laws FROM users WHERE meno!='$_SESSION[username]' order by meno asc");
$num=mysql_num_rows($sql);
echo "<form action='?page=laws//action=true//num=$num' method='post'>
<table width='153'>";
while($data=mysql_fetch_array($sql)){
if($data[laws] == '1'){$checked = "checked='checked'";}else{$checked = '';}
echo "
<tr>
<td width='121' align='right'><b>$data[meno]</b></td><input type='hidden' name='$data[uid]' value='0' />
<td width='20'><input type='checkbox' value='1' name='$data[uid]' $checked /></td>
</tr>";
}
?>
</table>
<input type="submit" value="ok" />
</form>
Štvrtok 27. 12. 2007, 20.05
Pridaj komentár!

  Gravatar povolený.




Kliknutím vložíš: Vlož smajla :-) Vlož smajla :-( Vlož smajla ;-) Vlož smajla :-D Vlož smajla 8-O Vlož smajla 8-) Vlož smajla :-? Vlož smajla :-x Vlož smajla :-P Vlož smajla :-|
Komentár je formátovaný Texy! syntaxou. Nie je povolené HTML, odkazy sa prevedú automaticky. Ak sa komentár nezobrazí, neprešiel bezpečnostnou kontrolou a ja ho musím schváliť. Nevkladajte ho prosím znovu.