Tutorials

Working with checkboxes and a database

Views: 145110
Rating: 4/5
Votes: 10

Introduction

Over in the php help forum, the question of how to deal with checkboxes arises pretty often. Usually, people want to be able to select which rows of a database to update/delete/throw out the window.

The concept is actually pretty simple. It involves naming your checkbox as an array and the use of the IN mysql clause. This tutorial aims to give a simple example in the hope that, next time someone asks, I can point them to a tutorial rather than explaining all over again.

Right, on with the show.

The Database

Seeing as we're going to be updating a database, we'll be needing a table and some data. Here's a table I made earlier:

CREATE TABLE `tutorial_users` (

`id` INT( 10 ) NOT NULL AUTO_INCREMENT ,

`username` VARCHAR( 50 ) NOT NULL ,

`admin` TINYINT( 1 ) NOT NULL DEFAULT '0',

PRIMARY KEY ( `id` )

) ENGINE = MYISAM

And some data to work with. No prizes for guessing what I was just watching on TV:

INSERT INTO `tutorial_users` (

`id` ,

`username` ,

`admin`

)

VALUES (

NULL , 'Stewie', '0'

), (

NULL , 'Peter', '0'

), (

NULL , 'Brian', '0'

), (

NULL , 'Meg', '0'

), (

NULL , 'Lois', '0'

), (

NULL , 'Chris', '0'

), (

NULL , 'Greased Up Deaf Guy', '0'

), (

NULL , 'Quagmire', '0'

);

It's a simple setup. A user's table with a field called admin, which is the field we'll be updating.

If you're the kind of guy (or gal; we're all for equal opportunities here) who likes a quick fix – the full code follows. Otherwise, we'll be breaking it down.

The Code

<?php
include("connect.php");
$updated = FALSE;
if(count($_POST) > 0){
    $admin = $_POST['admin'];
    array_map('intval',$admin);
    $admin = implode(',',$admin);
    mysql_query("UPDATE tutorial_users SET admin=0") or trigger_error(mysql_error(),E_USER_ERROR);
    mysql_query("UPDATE tutorial_users SET admin=1 WHERE id IN ($admin)") or trigger_error(mysql_error(),E_USER_ERROR);
    $updated=TRUE;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>phpfreaks checkbox tutorial</title>
</head>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
<?php
if($updated===TRUE){
    echo '<div>Privileges Updated!</div>';
}
?>
<table>
<tr>
<th>Username</th>
<th>Admin Privileges</th>
</tr>
<?php
$sql = "SELECT id,username,admin FROM tutorial_users ORDER by id ASC";
$result = mysql_query($sql) or trigger_error(mysql_error(),E_USER_ERROR);
while(list($id,$username,$admin)=mysql_fetch_row($result)){
    $checked = ($admin==1) ? 'checked="checked"' : '';
    echo '<tr><td>'.$username.'</td><td><input type="checkbox" name="admin[]" value="'.$id.'" '.$checked.'/></td></tr>'."\n";
}
?>
<tr><td colspan="2"><input type="submit" name="submit" value="Update Privileges" /></td></tr>
</table>
</form>
</body>
</html>

Interlude

Thanks for sticking around. Before we take a closer look at that code, I just want to mention a little about checkboxes and how they work.

You're probably aware that with a lot of other form elements, such as text fields, if you leave them blank they'll still appear in the $_POST/$_GET array – just with a blank value.

On the other hand, checkboxes behave a bit more like buttons. If you don't check them, they wont appear in the array. Assuming you do tick them, they'll take the value you give them or 'on' by default. Bear that in mind, it'll be important later.

Breaking it down

I'm going to start the breakdown a little way through the code from the opening form tag, seeing as you'll have to fill in that form before you can process it.

<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
<?php
if($updated===TRUE){
    echo '<div>Privileges Updated!</div>';
}

We have a standard form with a post method, and an action of the same page. We're also going to display a message if the database was updated – because we're nice like that.

<table>
<tr>
<th>Username</th>
<th>Admin Privileges</th>
</tr>

We're going to setup a table with the username and privilege listed in it. If you don't like tables, tough luck.

$sql = "SELECT id,username,admin FROM tutorial_users ORDER by id ASC";
$result = mysql_query($sql) or trigger_error(mysql_error(),E_USER_ERROR);

We select the fields we need from the database (not forgetting the id, as we'll use this to identify each row) and execute the query with a little error checking.

while(list($id,$username,$admin)=mysql_fetch_row($result)){

If you're not familiar with the list() construct, it allows us to assign lots of variables from a numerically indexed array in one go. I get bored of using $row all the time, so it makes a change. It's important to use mysql_fetch_row() so that you get a numerically indexed array (as opposed to an associative one) and that you create the variables with the same order you selected them in your query. See the manual page [http://www.php.net/list] for a bit more.

$checked = ($admin==1) ? 'checked="checked"' : '';
    echo '<tr><td>'.$username.'</td><td><input type="checkbox" name="admin[]" value="'.$id.'" '.$checked.'/></td></tr>'."\n";

Inside that loop, we first work out if the checkbox should be ticked to start with. That is, if the user currently has admin privileges. Use of the ternary operator keeps this short and sweet. We then echo out a row for each user.

Notice that we name the checkbox admin[]. This means that $_POST['admin'] is going to be an array. An array of all the ticked boxes in fact. Also notice that we set the value to the id of the user.

<tr><td colspan="2"><input type="submit" name="submit" value="Update Privileges" /></td></tr>
</table>
</form>
</body>
</html>

Finally, we make a submit button and finish off our html. I don't know about you, but I find forms without a submit button a little unsatisfactory.

Next, we'll take a look at the processing.

Processing the form

include("connect.php");
$updated = FALSE;

First, we include a file that's going to connect us to our database. I would show you that file, but personally I prefer to keep my username and password to myself. We also create a variable that says we haven't updated the database...yet.

if(count($_POST) > 0){
    $admin = $_POST['admin'];
    array_map('intval',$admin);

Our if statement ensures that this code only runs if the form has been submitted. We create a local variable from the $_POST array. We then do a little bit of validation. We don't want any nasty users modifying any of those values in our form to do some SQL injection, so we make sure every value in that array is an integer with the array_map function. Again, see the manual page [http://www.php.net/array_map] if you're not too sure how this function works.

"What if I don't have integers as my values?" Good question. You might like to use mysql_real_escape_string(), like so:

array_map('mysql_real_escape_string',$admin);

Or you might write your own function to make sure the values are the sort of thing you expect.

$admin = implode(',',$admin);

Next, we use the implode() function to turn our array into a string. We separate each value with a comma. This will allow us to use the IN clause in a moment. If your values aren't integers, you'll have to do something different. I'll cover that in a minute.

mysql_query("UPDATE users SET admin=0") or trigger_error(mysql_error(),E_USER_ERROR);
    mysql_query("UPDATE users SET admin=1 WHERE id IN ($admin)") or trigger_error(mysql_error(),E_USER_ERROR);
    $updated=TRUE;

Before we update the new users who have admin privileges, we first update the database so no-one does. Why? Well, our comma-delimited list contains just those people who we do want to have admin rights. So we better make sure no-one else does. Our second query makes use of that IN clause – it allows us to provide a comma-separate list of values that id can be.

Note: An alternative to updating every row to 0 would be to use the NOT IN clause.

Using strings

If your values are strings, you'll need to be a little more careful with your implode and query. Don't forget that all strings in your SQL must be inside quotes. It's a pretty simple adjustment, but it'll cause you an error if you forget. Make your implode look like this:

$admin = implode("','",$admin);

And your query like this:

mysql_query("UPDATE users SET admin=1 WHERE id IN ('$admin')") or trigger_error(mysql_error(),E_USER_ERROR);

Note the extra quotes – after we've imploded our values, they might look a little like this:

one','two','three','four

So we need to add the quote to the front and back.

And that's that. All we've got time for now is a short summary

Summary

So there we have it. The form gets processed and reloaded with the users having the new privileges. I hope that was easy to follow and worth the effort. Next time you work with checkboxes, it should be a little easier – there's really not much more to it.

Remember to name your checkbox as an array and set its value to something that uniquely identifies the row. If that's a string, take care when you implode the data. And don't forget to validate those values too. Most users are evil. Alright, maybe not. But if you think like that, you'll save yourself more than a few headaches.

Lastly, don't forget, you can name other pieces of your form so that they are arrays. Again, this is useful for updating an unknown, large amount of data simultaneously.