Forum Moderators: coopster

Message Too Old, No Replies

posting checkbox values in an array

         

mattennant

12:02 am on Sep 3, 2008 (gmt 0)

10+ Year Member



hi all

i have a script i'm working on for relating articles, i've made progress, but ground to a bit of a halt .
The problem is this, the script below works fine for updating multiple row in the data base, but when i try an d change the text field to a check box everything goes to pot, basically i want to pass the checkbox checked as 1 and unchecked as 0

script working fine like so


while($rows=mysql_fetch_array($result777)){
echo '<input name="rank[]" type="text" value="'.$rows['rank'].'"/>';
echo '<input name="keyword_id[]" type="hidden" value="'.$rows['keyword_id'].'"/>';
echo '<input name="id[]" type="hidden" value="'.$rows['keywordrank_id'].'"/>';
}

and up above

for($i=0;$i<$count;$i++){
$sql85="UPDATE keyword_rank SET keyword_id='$keyword_id[$i]', rank='$rank[$i]' WHERE keywordrank_id='$id[$i]'";
$result85=mysql_query($sql85);
}
if($result85){
//}
$updateGoTo = "index.php?nav=" . $category ;
header(sprintf("Location: %s", $updateGoTo));

i've tried the many option s including the following , but i'm struggling, seems like it should be so obvious.


while etc
echo '<input name="rank[]" type="checkbox" value="'.$rows['rank'].'"';
if (($rows['rank']) == '1') {echo "checked=\"checked\"";}
echo'/>';
echo '<input name="keyword_id[]" type="hidden" value="'.$rows['keyword_id'].'"/>';
echo '<input name="id[]" type="hidden" value="'.$rows['keywordrank_id'].'"/>';

and above

for($i=0;$i<$count;$i++){
echo $rank[$i].'-'. $i.'<br />';//error check
if (empty($rank[$i])){
$rank[$i] = 0;
}else{
/$rank[$i] = 1;
/}
$sql85="UPDATE keyword_rank SET keyword_id='$keyword_id[$i]', rank='$rank[$i]' WHERE keywordrank_id='$id[$i]'";
$result85=mysql_query($sql85);
}

cameraman

12:34 am on Sep 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There isn't a value for unchecked. If a checkbox is checked it will have the value you specify, but if not, it just won't be there. Even more fun, if they're arrayed like you're doing there won't even be a blank spot in the array; the checked ones will all get squished together because the array isn't actually built until post time.

It gets really tricky when you're dealing with several arrays like you are because they're going to get out of sync. Let's say you have ten items. The visitor leaves the very first checkbox unchecked and checks all the others. The resulting checkbox array is going to have 9 elements while the other arrays still have 10, and the checkboxes will all be off by one ($rank[0] now corresponds to $keyword_id[1]).

mattennant

8:18 am on Sep 3, 2008 (gmt 0)

10+ Year Member



its almost a relief that , that is the case as i spent so long pottering around with this yesterday, only to consatntly get the exact same situation you explained.

i have 5 categories, each category should have two radio groups (unrelated and related)

but this too seemed to cause havoc, and all the radio buttons 10 were relted, is this just the nature of the beast and i have to stick with text boxes or is there another neater solution?

cameraman

8:49 am on Sep 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can definitely use the checkboxes; knowing that unchecked ones don't exist is over half the battle. If you make sure that you start off with a radio button checked you shouldn't have any problem with those.

There's a couple of ways that I can think of right off the bat that you can handle checkboxes. You can index them explicitly:

while etc
echo '<input type="checkbox" name="rank[' . $rows['keywordrank_id'] . ']" value="' . $rows['rank'] '"';
if($rows['rank'] == '1') echo ' checked="checked"';
echo '/>';
echo '<input type="hidden" name="keyword_id[' . $rows['keywordrank_id'] . ']" value="' . $rows['keyword_id'] '"';

See how I used keywordrank_id for both elements? That will keep them synced and you can use that during your update.
foreach($_POST['rank'] as $keywordrank_id => $value) {
$keyword_id = $_POST['keyword_id'][$keywordrank_id];
}

Using the foreach construct you only pick up the ones that have been checked.

The other way involves variable variables. What you do is instead of using arrays, append the id onto the end of the element's name, so you end up with check1, check2, check15, etc. The above will probably be a little easier to handle, though.

mattennant

10:59 am on Sep 3, 2008 (gmt 0)

10+ Year Member



thanks cameraman

am feeling slightly lost in a sea of arrays, i really want to understand this but i'm struggling a bit. here are my queries

does what you suggested affect the following columns

keywordrank_id - this is the unique primary key to the table
article_id - this is the article that the checkboxes relate to
keyword_id - this is the category the checkbox refers to
rank - this is either to be 1 or 0

now i think my understanding could be wrong, but is the code above, looking to combine some of the above. or am i just missing the logic.

if not, would i run the foreach loop before the update loop, or instead of the update while loop? ie


foreach($_POST['rank'] as $keywordrank_id => $value) {
$keyword_id = $_POST['keyword_id'][$keywordrank_id];
}
for($i=0;$i<$count;$i++){

$sql85="UPDATE keyword_rank SET keyword_id='$keyword_id[$i]', rank='$rank[$i]' WHERE keywordrank_id='$id[$i]'";
$result85=mysql_query($sql85);
}

Thanks for your help as usual, appreciated

mat

cameraman

7:36 pm on Sep 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No, it doesn't combine anything, I was just showing you in an abbreviated manner how you can retrieve the data from the form. I see where I started to confuse you - I had gotten it into my head that you only wanted to update rows that had the checkbox set, but looking at it again I see that you want to set rank = 1 if the box is set and 0 if it's not.

When you build the form, use the keywordrank_id as the explicit index for each of your various arrays; you're using that since that's the primary key to the table. When the form is posted, the checkbox array will contain only those which have been checked. Let's say that you built the form with 10 'sets', and that their keywordrank_id is numbered 1 through 10. Then you check items 4, 6, 9, and 10. If you were to do this in response to the post:

foreach($_POST['rank'] as $index => $value)
echo "<div>Checkboxes: $index = $value</div>";

foreach($_POST['keyword_id'] as $index => $value)
echo "<div>Hidden keyword_id's: $index = $value</div>";

foreach($_POST['id'] as $index => $value)
echo "<div>Hidden id's: $index = $value</div>";

You'd see four checkboxes listed, but you'd see all ten of the other ones listed. But, since the index for all of the arrays is the same, they're still in sync, and the index is the keywordrank_id - the unique primary key to the table. And actually, you can now drop your hidden id because you're already tracking it in the index - that third group of echos should be producing 1=1 2=2 3=3 etc.

Because the array index is no longer a 0-9, it's better to use foreach instead of the for, and you want to use an array that has all its elements to drive the loop since you want to update all of the rows:

foreach($_POST['keyword_id'] as $keywordrank_id => $keyword_id) {
$rank = isset($_POST['rank'][$keywordrank_id]) ? 1 : 0;
$sql85="UPDATE keyword_rank SET keyword_id='$keyword_id', rank='$rank' WHERE keywordrank_id='$keywordrank_id'";
$result85=mysql_query($sql85);
}

I did $rank that way because you're going to have mixed values from the form. If you look at the way you populate it, some will have a value of 0 and others will have value of 1. I'm understanding from your first post that if it's checked you want a 1 and if it's unchecked you want a 0.

Are keywordrank_id and keyword_id always numeric, and are the table fields set to a numeric type (tinyint, bigint, float, double)?

mattennant

10:11 pm on Sep 3, 2008 (gmt 0)

10+ Year Member



Cameraman you rule. Thanks for the really clear information, helps so much. and working a treat!

Keyword_rank and keyword_id are always numeric, they are set to interger , would i be better off looking at one of the other types you mentioned?

As an aside, but heavily connected with this same functionality, you helped me in a previous post with a mysql statement for extracting related articles.

[webmasterworld.com...]

I've been working on the statement today to bring together articles with related checkboxes. And things appear to be going very well.

I've started to investigate the possibility of three radio buttons, (very related - slightly related - and not related at all) values 2-1- 0 - this is by no means necessary, but you know how it is.

Anyway the story so far is this


SELECT c.article_id , c.headline, d.keyword_id , d.rank = (Select Max(d.rank ))
FROM articles c, keyword_rank d
WHERE (((d. rank = 1 ) or (d. rank = 2))
AND (d.article_id=c. article_id) AND (c. article_id !=34)
AND (d.keyword_id IN (SELECT keyword_id from keyword_rank where article_id = 34)))
Group By d.rank
ORDER by d.rank DESC

This is all well and good and working just dandy, only thing is it places no real weight on whether a match of 2 or 1 is found, would be really neat to get a weighted list. except in the ordering, but even then the article referred to by the article id may only have been checked with slightly related, yet the related article checked very related would come out on top.

was wondering if incorporating some kind of if statement in the select statement, or maybe a case of resorting to two select statements and displaying one below the other.

Thanks again, it's made my evening seing those blue tick in those little boxes, cheers.

cameraman

6:10 am on Sep 4, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It may be that group by. What happens if you take it out (leave the order by)? I always have to futz around with grouping; it never works the way I expect it to. If that doesn't work, you could sort the array of results with usort() [us.php.net]

I asked about the field types because of form security. If you're the only one who can ever navigate to this form you're ok, but if the general public can get to it that's a different matter. Never, ever trust data that comes in. In this case, you want to "sanitize" the data here:
foreach($_POST['keyword_id'] as $keywordrank_id => $keyword_id) {
$keywordrank_id = intval($keywordrank_id);
$keyword_id = intval($keyword_id);

Always be as restrictive as you can - if it's supposed to be a number, make sure it's a number with intval() or floatval(). If it's supposed to be a word from a finite list, check it against an array with in_array(). If it can be any text, then use mysql_real_escape_string.