Click to See Complete Forum and Search --> : [RESOLVED] Multiple insert into single Database field?


Design-is-BS
05-15-2008, 02:19 PM
I am trying to take check-boxes which have been checked and display their names (separated with commas or spaces) into a Database field with a column of "checked".

I already have the column on my DB, I just need to find a way to submit more than one, but not all of the values for checked boxes. Each box is given a name: "purchstat_(a-v)" and the user decides which to select.

This is my code for determining which box(es) the user has selected:


if (isset($_REQUEST['purchstat_a'])) {
$purchstat_a = "purchstat_a";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_b'])) {
$purchstat_b = "purchstat_b";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_c'])) {
$purchstat_c = "purchstat_c";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_d'])) {
$purchstat_d = "purchstat_d";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_e'])) {
$purchstat_e = "purchstat_e";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_f'])) {
$purchstat_f = "purchstat_f";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_g'])) {
$purchstat_g = "purchstat_g";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_h'])) {
$purchstat_h = "purchstat_h";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_i'])) {
$purchstat_i = "purchstat_i";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_j'])) {
$purchstat_j = "purchstat_j";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_k'])) {
$purchstat_k = "purchstat_k";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_l'])) {
$purchstat_l = "purchstat_l";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_m'])) {
$purchstat_m = "purchstat_m";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_n'])) {
$purchstat_n = "purchstat_n";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_o'])) {
$purchstat_o = "purchstat_o";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_p'])) {
$purchstat_p = "purchstat_p";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_q'])) {
$purchstat_q = "purchstat_q";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_r'])) {
$purchstat_r = "purchstat_r";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_s'])) {
$purchstat_s = "purchstat_s";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_t'])) {
$purchstat_t = "purchstat_t";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_u'])) {
$purchstat_u = "purchstat_u";
} else {
//nothing
}

if (isset($_REQUEST['purchstat_v'])) {
$purchstat_v = "purchstat_v";
} else {
//nothing
}


The values of the checked boxes display fine into the address bar:

"purchstat_a&purchstat_f&purchstat_k&purchstat_o&purchstat_q"

Now I think it might be because I don't have something like:

"checked=purchstat_a&purchstat_f&purchstat_k&purchstat_o&purchstat_q"

but I doubt it.

My update query is:


$query = "UPDATE users SET agreamount = '$aggreAmount', checked = '$purchstat_a, $purchstat_b, $purchstat_c, $purchstat_d, $purchstat_e, $purchstat_f, $purchstat_g, $purchstat_h, $purchstat_i, $purchstat_j, $purchstat_k, $purchstat_l, $purchstat_m, $purchstat_n, $purchstat_o, $purchstat_p, $purchstat_q, $purchstat_r, $purchstat_s, $purchstat_t, $purchstat_u, $purchstat_v', date = '$date', secpurch = '$secsPurchased', ABC_Confirm = '$ABC_conf' WHERE username='$user_username'";


It might not be obvious, so I'll try to explain. I will use purchstat_a as an example. the code first checks in purchstat_a is in the address bar by $_REQUEST'ing it. If it is set, then the code declares that $purchstat_a = "purchstat_a". So, in turn, it should then put purchstat_a into the Database. It repeats for any other purchstat declared.

Thing is, it's only adding commas, which I've decided to use to separate each value. I wasn't able to find this anywhere on the web, at-least I didn't know what to search for.

Thanks for anyone's help!

sstalder
05-16-2008, 09:35 AM
This is untested but I think it should work. There is absolutely no need to make that many static if / else statements, you should learn to utilize loops for things like this :)

$query = "UPDATE users SET agreamount = '$aggreAmount', checked = '";

for($letters = range('a','v'), $i = 0; isset($letters{$i}); $i++) {
if(isset($_REQUEST['purchstat_'.$letters{$i}])) {
$query .= $_REQUEST['purchstat_'.$letters{$i}].",";
}
}

$query .= "', date = '{$date}', secpurch = '{$secsPurchased}', ABC_Confirm = '{$ABC_conf}' WHERE username='{$user_username}';";

Design-is-BS
05-19-2008, 09:48 AM
Thanks for replying, Steve,

After I posted this thread I didn't get any responses, so I decided to go looking around for a answer. I came across this forum:
http://forums.asmallorange.com/lofiversion/index.php/t9456.html

The user has a very similar problem as me. am using checkboxes and want to relay the values to a single DB field. I was wondering if this method would also be a good choice. I feel more comfortable using arrays.

sstalder
05-19-2008, 09:54 AM
Yeah that would also be a method to use. I assumed you had a reason to use a-v so I coded something for that use. But you should use whatever is easier for you.

Design-is-BS
05-19-2008, 10:02 AM
Using the other forum I have already come this far:
PETE:
<input type="checkbox" name="checkbox[0]" value="whatever" />
<input type="checkbox" name="checkbox[1]" value="whatever2" />
<input type="checkbox" name="checkbox[2]" value="whatever3" />
<!-- etc -->


The next step would be to:
PETE:
<?php
//Assuming you do relevant checks
implode(', ', $_POST['checkbox']);
?>


I'm sorry but even-though I'm more comfortable with arrays, I still don't know a whole lot about them. Is there anyway you could explain this to me? Thanks Steve.

Design-is-BS
05-19-2008, 10:35 AM
I'm going to take back that earlier response. I think your method is much easier for me and I won't have to revamp my code in order to accommodate it.

I tried using it and my DB still isn't updated, however.

Code:

<?php

$user_username = $_REQUEST['username'];
$secsPurchased = $_REQUEST['secpurch'];
$aggreAmount = $_REQUEST['aggreamount'];
$date = date("d/m/y");
$termsConf = $_REQUEST['termsconfirm'];
$purchStatConf = $_REQUEST['accredinvestor'];
$subscrConf = $_REQUEST['subscriptconfirm'];

if($termsConf == 1 && $purchStatConf == 1 && $subscrConf == 1) {
$ABC_conf = "1";
} else {
$ABC_conf = "0";
}
if (isset($_REQUEST['username'])) {

//Check Connectivity
if(!is_resource($link)) {

echo "Failed to connect to the server\n";
// ... log the error properly

} else {
/*//Make a safe query
$query = "UPDATE users SET agreamount = '$aggreAmount', checked = '$purchstat_a, $purchstat_b, $purchstat_c, $purchstat_d, $purchstat_e, $purchstat_f, $purchstat_g, $purchstat_h, $purchstat_i, $purchstat_j, $purchstat_k, $purchstat_l, $purchstat_m, $purchstat_n, $purchstat_o, $purchstat_p, $purchstat_q, $purchstat_r, $purchstat_s, $purchstat_t, $purchstat_u, $purchstat_v', date = '$date', secpurch = '$secsPurchased', ABC_Confirm = '$ABC_conf' WHERE username='$user_username'";
$fetch = mysql_query($query, $link);*/


$query = "UPDATE users SET agreamount = '$aggreAmount', checked = '";
for($letters = range('a','v'), $i = 0; isset($letters{$i}); $i++) {
if(isset($_REQUEST['purchstat_'.$letters{$i}])) {
$query .= $_REQUEST['purchstat_'.$letters{$i}].",";
}
}
$query .= "', date = '{$date}', secpurch = '{$secsPurchased}', ABC_Confirm = '{$ABC_conf}' WHERE username='{$user_username}';";
if (mysql_affected_rows() >= 1) {
//continue
} else {
echo "error";

}




}
}
?>

"error" is echo'd

SyCo
05-19-2008, 02:00 PM
A few notes on your script, you say "The values of the checked boxes display fine into the address bar" so your form method is either GET or not set so defaulting to GET. As you're using a form then I'd suggest you use POST not GET as $_REQUEST opens you up to URL hacking easily (I can simply change what the url says). Unless you need to access GET or COOKIE and POST in different ways all the time then it's less secure to use $_REQUEST.

for example

You'd think using checkboxes would be safe from SQL injection but it's not and especially so using GET in forms.
Heres your query when $aggreAmount is checked.
Example GET URL
www.site.com?agreamount=400&purchstat_a=yes&purchstat_b=no&$purchstat_a=yes
//resulting query
$query = "UPDATE users SET agreamount = '400', checked = 'yes,no,yes... etc

a quick URL hack later and here's mine
www.site.com?agreamount=400&purchstat_a=yes';drop table users;
'//DO NOT RUN THIS!!!!
$query = "UPDATE users SET agreamount = '400', checked = 'yes';drop table users;

SQL will run both queries, first the update (with errors), then the drop. oops! Using cURL it's almost as easy to do the same thing with POST but with GET it's script kiddy time.

Google sanitize inputs in php and mysql, lots of good advice already out the on how to fix this.

Another note, this is redundant

else {
//nothing
}


You don't need the 'else' if it doesn't do anything this is neat syntax when it's a simple 'if' without an 'else'.
if (isset($_REQUEST['purchstat_f'])) $purchstat_f = "purchstat_f";


At first glance it looks like a good idea to use a CSV of the checkbox ids and depending on how big your application is going to get it might work fine. Thing is it's pretty slow to retrieve the text/varchar column of and ids explode them. It's also a waste of space as what if your app grows too big to store the ids in a varchar, you'll need 'text' column type which is a waste of space for a list of ids.

A much faster and neater way is to use another table that relates checkbox ids to the entry's id. Your 'checkbox ids' table only needs to store the ids of the checkboxes that were checked. No check no record. Although it uses another table you can make the id columns 'ints' so they'll join really fast (if you index both userid columns).

table 1 users
userid
name
agreamount
etc

table2purchstats
userid
purchstat_id

purchstat_a could be purchstat_1 and you store the 1. Number are faster than letters in SQL. If there is a record in the second table for the purchstat_id you can check the box when you draw the form.

The multiple inserts can be done with a single query like this

INSERT INTO table2purchstats (userid,purchstat_id)
VALUES
(1, 34),
(2, 44),
(3, 53);

create the list of id pairs dynamically in a loop.

The neatest part of using the second table is the ease of future expansion. Currently, if you add a new checkbox in the future, you'll need to edit your SQL and your form. With the second table method you only need to add the checkbox to the form with your purchstat_ naming convention and you're done. On submit of your form, your code can look through the POST array for keys (input names) with purchstat_ and save them to the ids table, checkboxes are not posted if not checked.

When you draw the form for editing you can retrieve the ids to check by joining the two tables or do 2 look ups and first store all the checkbox ids into an array of key/values pairs then use the key (in this case userid) to check the box if a record exists.

I'd even go as far as drawing the checkboxes from another table. Then adding a next checkbox, handling the data storage and whether it's checked can all be done simple by adding a row to you checkboxes table. The code doesn't need editing again if it's done right the first time.

It all depend on if the effort is worth the reward. I have a checkbox list of security requirements for users on a big site. The requirements change constantly so that requires maintenance (adding removing checkboxes or user permissions) so it's worth it for me. I can manage 1000's of users and 10's of checkboxes (currently 80) without having to touch the code. It's more complex to set up but it's cake to administrate and doesn't waste data.

It's be a good thing to get your head around as you're learning as later you'll have the principles down when you come to do a bigger site.

Design-is-BS
05-20-2008, 08:06 AM
Thank you for replying SyCo,

That was a lot to chew (lol) so let me see if I can grasp this.


INSERT INTO table2purchstats (userid,purchstat_id)
VALUES
(1, 34),
(2, 44),
(3, 53);

So what I'm doing here is, I'm taking all of my checkboxes, going through the, determining what is checked, and those that are checked (numbered 1 through 21) I want to assign a number for the database organization:

(1, 34),
(2, 44),
(3, 53);

//could just as well be

(1, 12),
(2, 3),
(3, 18);


Right?

Well my questions is, should I:

1) Go through my code a change (purchstat_a, purchstat_b) to (purchstat_1, purchstat_2)?
2) How do I then determine what is checked an not checked, like this?:

if (isset($_REQUEST['purchstat_1'])) $purchstat_1 = "purchstat_1");
if (isset($_REQUEST['purchstat_2'])) $purchstat_2 = "purchstat_2");

3) How do I then tell the Database why I am inputting numbers? Or am I just sending them in and determining what is checked later, according to what numbers are in the Database?
4) And then (whew) how do I then tell the DB to accept certain boxes which are checked? Like this?:

$query = "INSERT INTO table2purchstats (userid, purchstat_id) VALUES (1, 12), (2, 4), (3, 21);


Thanks again SyCo

bokeh
05-20-2008, 08:16 AM
I am trying to take check-boxes which have been checked and display their names (separated with commas or spaces) into a Database field with a column of "checked".Not a good idea. It means the database engine is not going to be able to use these value for retrieving data.

Design-is-BS
05-20-2008, 08:19 AM
So is this a lost cause? I mean, SyCo's theory makes sense.

bokeh
05-20-2008, 08:47 AM
So is this a lost cause? I mean, SyCo's theory makes sense.The problem is the data is useless without the script because it is order dependent and stores more than one value in one field. Imagine later, for a reason that is not yet apparent, you wish to SELECT all the people that checked inputs 1 and 3 but not 2. The database cannot do this and so rather than use its built-in, optimised functions you would instead need to write a custom script that selects every row in the table and runs through them individually. Now imagine trying to do the same thing with a join or other multiple table dependent query. I think I see a coding nightmare coming on.

Design-is-BS
05-20-2008, 09:49 AM
The problem is the data is useless without the script...

What script are you referring to?

SyCo
05-20-2008, 10:52 AM
Bokeh, I think you're commenting on the original CSV storage method, right? I thought that was a bad enough idea to write quite a lengthy post in reply. Did you read it because it's being commented on and I don't think you read it. If you have any thoughts on my suggestion I'd be happy to hear them.

it is order dependent

My suggestion isn't, it's ID dependent so you can do what ever retrievals you want. I use this system on a very large, complex site and it's very fast and flexible.

you wish to SELECT all the people that checked inputs 1 and 3 but not 2.

Again not easy with a CSV (you can explode but way slower than well structured tables) but with my suggestion, pretty simple.

SELECT * FROM users
inner join table2purchstats on users.userid=table2purchstats.userid
WHERE purchstat_id in (1,3)

the 'in id()' list can be generated dynamically too so it's very flexible.


So what I'm doing here is, I'm taking all of my checkboxes, going through the, determining what is checked, and those that are checked (numbered 1 through 21) I want to assign a number for the database organization:

You don't have to determine what is checked. Only checked values will exist in the POST array.
the two values in parenthisis eg (1, 34) are the values for your columns eg (userid,purchstat_id). Userid is likely to be the same for the insert (and is taken from the login credentials) and the id can be ascertained by 'preg'ing for any posted values containing 'purchstat_'. If they do you can either extract the id eg with preg_replace() 'purchstat_' with '' leaving the number or explode on the underscore and take the second part of the array.

So you can create an array of ids to insert

foreach($_POST as $key => $value){
if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}
}

http://us3.php.net/manual/en/function.preg-match.php

and dynamically create a SQL statement


if(count($ids)>0){//check at least one box was checked
$q="INSERT INTO table2purchstats (userid,purchstat_id)
VALUES";

foreach($ids as $v){
$q.=' ('.$userid.','.$v.'),';
}
//substr() off the final comma

//insert statement within count if()
}

(If you're feeling adventurous you can combine the two loops, I'm just trying to keep things clear.)

As its a checkbox you don't usually have to worry about the value, just if it's checked or not so the key (input name) is more important.

If you have other values to insert such as name, address etc then do it to the users table in a separate statement.


Go through my code a change (purchstat_a, purchstat_b) to (purchstat_1, purchstat_2)?

Yea. If you stored your checkboxes in a table as well you would only have to update a single echo in loop :) There's no reason storage wise why you couldn't store letters but numbers can be given a 'int' data type that are faster in joins than varchars. You need to learn about indexing columns for maximum efficiency. You'll have to ask another question for that as I'm a little fuzzy on MySQL indexing.

How do I then tell the Database why I am inputting numbers?
Because you're only storing the checked boxes. If there not checked you store nothing saving space and making it simple to determine if the box should be checked when you draw the form again for an edit. No record no check mark.


And then (whew) how do I then tell the DB to accept certain boxes which are checked? Like this?:
See above! whew indeed!

I hope this is making sense!! It took me a while when I learned it too but is a much better method of string the ids than a CSV.

PS I've not tested any of the code here so watch out for syntax errors, my usual caveat... consider all code pseudo code! Also I'm using MSSQL these days so my SQL should be OK as I remember but will need checking!!

bokeh
05-20-2008, 03:48 PM
Bokeh, I think you're commenting on the original CSV storage method, right?Yes!

SyCo
05-20-2008, 03:59 PM
Ahh! I'm glad that's cleared up.
lol

Chazzl
05-20-2008, 11:09 PM
I second SyCo's method. ^.^

Will be much more flexible and easier to work with.

Design-is-BS
05-21-2008, 08:14 AM
Well I feel much more comfortable now, knowing that others are behind you SyCo. Hehe.

First-off, this is where I inserted the code:
<?php

$user_username = $_REQUEST['username'];
$secsPurchased = $_REQUEST['secpurch'];
$aggreAmount = $_REQUEST['aggreamount'];
$date = date("d/m/y");
$termsConf = $_REQUEST['termsconfirm'];
$purchStatConf = $_REQUEST['accredinvestor'];
$subscrConf = $_REQUEST['subscriptconfirm'];

if($termsConf == 1 && $purchStatConf == 1 && $subscrConf == 1) {
$ABC_conf = "1";
} else {
$ABC_conf = "0";
}


if (isset($_REQUEST['username'])) {

//Check Connectivity
if(!is_resource($link)) {

echo "Failed to connect to the server\n";
// ... log the error properly

} else {
foreach($_POST as $key => $value){
if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}
}
if(count($ids)>0){//check at least one box was checked
$q="INSERT INTO table2purchstats (userid,purchstat_id)
VALUES";

foreach($ids as $v){
$q.=' ('.$userid.','.$v.'),';
}
//substr() off the final comma

//insert statement within count if()
}
}
}
?>

Now I'm looking at this Code and just have a couple questions:

1) When you say "foreach($_POST ad $key => $value)" does that then say that for each post with the variable $key make it equal to $value?
2) "if(count($ids)>0)" When I see this I keep wondering where $ids comes from. Does that come from the page that submits data onto this one (summary.php)

Thanks so much SyCo

sstalder
05-21-2008, 08:20 AM
1) $key will equal the 'post variable name' (i.e. 'username') and $value will equal the usernames value that is passed.
2) I would assume $ids should equal your checkbox name but I don't know where it is set or declared in the code. Your checkbox's would reflect:

<input type'textbox' name'ids[]' />
<input type'textbox' name'ids[]' />
<input type'textbox' name'ids[]' />
<input type'textbox' name'ids[]' />

From what I could gather that should do the trick.

Design-is-BS
05-21-2008, 08:59 AM
would I put anything in ids[]?

something like: ids[1] or ids[a]?

SyCo
05-21-2008, 09:45 AM
sorry I edited the post to make the array name easier to understand but didn't update the foreach

ids should be $ids_to_insert so count() is looking to see there is at least one checked checkbox.

You can use foreach() to loop through an array

foreach($array as $key => $value)

foreach loop through the array and assigns the key and value of the array to the new variables. You could call them

foreach($array as $foo => $bar)

But $key, $value (or $k, $v) makes sense usually. (You can nest foreach loops for multidimensional arrays, then it makes sense to name the keys or values as appropriate.)

When the form is submitted the $_POST array is created automatically. It will contain all the submitted information name, address, anything in the form. So this is a 2 part process. One part will submit the name/address etc data and retrieve the last inserted id (with mysql_insert_id() I think) which will give you your userid to use in the second insert in your second table containing the ids.

let me go through this one again
foreach($_POST as $key => $value){
if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}
}

As sstalder says the input names become the POST array's keys and the value assigned to the checkbox is passed to the POST array's value. As it's a check box the value is not really important, just the key, because if the key is in the array the box was checked, if it's not in the array it wasn't checked.

so as an example form

<input type="text" name="name" value="">
<input type="text" name="age" value="">
<input type="checkbox" name="purchstat_1" value="foo">
<input type="checkbox" name="purchstat_2" value="foo">
<input type="checkbox" name="purchstat_3" value="foo">

If the first and second checkboxes are checked but not the third the POST array might look something like this.

POST(
name => bob
age => 64
purchstat_1 => foo
purchstat_2 => foo
)


The above loop will build an array like this

ids_to_insert(
purchstat_1 => foo
purchstat_2 => foo
)


no purchstat_3 in the array. The values are irrelevant as the key contains the information. You could assign the id to the value and use that as well, thats up to you and completely valid too.

So the above code will loop through the POST array and use preg_match() to see if any of the POST array values have a key with 'purchstat_'. if they do its a checkbox so the next job is to strip off the purchstat_ (using preg_replace() so all that's left is the number at the end. This number will match the corresponding checkbox in your form. In this case for ease of seeing what's going on I've assigned to to an array. This array will get filled with the ids of the checked checkboxes only. Of course for this to work all checkboxes must have the prefix 'purchstat_' and a different id number for each one.

Next count the array to see there's at least one element from a checked box and if so begin building the SQL query.

don't forget to use substr() to remove the final comma or the query will break with a syntax error.

When making dynamic queries its a good idea to echo them to the screen instead of running them until you are sure they look right.

Design-is-BS
05-21-2008, 12:52 PM
I'm trying to troubleshoot this code. At the moment when I display the checked boxes (on summary.php) all of the unchecked & checked boxes appear.

The boxes come form agreement3.php (http://designisbs.ca/johnbursic/webdevel/agreement3.rtf), then the boxes are sent to summary.php (http://designisbs.ca/johnbursic/webdevel/summary.rtf) where they are reviewed by the user and then finally put onto the Database on congrats.php (http://designisbs.ca/johnbursic/webdevel/congrats.rtf). the include (check boxes) is checkedboxes.php (http://designisbs.ca/johnbursic/webdevel/checkedboxes.rtf)

I linked all of the pages' text files. I apologize for this as there are too many characters to post them here. Please let me know if this is inappropriate.

I decided to try it anyways, and got:
Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in /.../congrats.php on line 39

Line 38, 39, 40:

if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}

SyCo
05-21-2008, 01:19 PM
It'd be easier to click to a web page rather than download files to my HDD, it's a bit of a hassle and is against our office policy to download files from unknown sources.

Your theory sound fine to me. You should be able to get it to work using the 3 pages.

Also error is because.
typo - missing ( after preg_replace

All my code is pseudo code. :)
I need to add that to my sig!!

Chazzl
05-21-2008, 01:51 PM
Alternative method for the same outcome would be to set your checkboxes as arrays within the HTML name attribute.

<input type="text" name="name" value="">
<input type="text" name="age" value="">
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">
<input type="checkbox" name="purchstat[3]" value="foo">

This will cause PHP to load the values of purchstat as an array such as:
purchstate => Array
[1] => foo
[2] => foo
[3] => foo

Now you can skip the need for preg_match and preg_replace altogether and jump straight into setting up your database query.


<?php

$user_username = $_REQUEST['username'];
$secsPurchased = $_REQUEST['secpurch'];
$aggreAmount = $_REQUEST['aggreamount'];
$date = date("d/m/y");
$termsConf = $_REQUEST['termsconfirm'];
$purchStatConf = $_REQUEST['accredinvestor'];
$subscrConf = $_REQUEST['subscriptconfirm'];

if($termsConf == 1 && $purchStatConf == 1 && $subscrConf == 1) {
$ABC_conf = "1";
} else {
$ABC_conf = "0";
}


if (isset($_REQUEST['username'])) {

//Check Connectivity
if(!is_resource($link)) {

echo "Failed to connect to the server\n";
// ... log the error properly

} else {
/* Obsolete
foreach($_POST as $key => $value){
if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}
}
*/
if( 0 < count($_POST['purchstat']) ){ //check at least one box was checked
$q="INSERT INTO table2purchstats (userid,purchstat_id)
VALUES";
foreach($_POST['purchstat'] as $v){
if( is_numeric($v) ){
$q .= " ($userid,$v),";
}
}
//substr() off the final comma

//insert statement within count if()
}
}
}
?>


Don't forget to sanitize your database queries ;)

SyCo
05-21-2008, 02:02 PM
That's very neat chazzl!

Definitely sanitize
http://xkcd.com/327/

Chazzl
05-21-2008, 02:27 PM
Whoops... the foreach loop should be setting the key value in $q... I overlooked that when modifying it. Here is the corrected chunk:


foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
}
}

Design-is-BS
05-22-2008, 09:42 AM
Ok, I'll do the square brackets (unless someone else has another idea lol) but I don't want to screw this up. So I'm going to put the square brackets in these spots:
name=purchstat[2]
if(isset($_POST['purchstat[3]'])) {
$purchstat_1 = $_POST['purchstat[1]'];

Basically I don't want to put it in a variable, right? Like this?:
$purchstat[1]

Because I think that'll cause problems.

I'll also give the checkboxes a value of purchstat_1 through purchstat_22

Also, this is my SySQL query with sanitize:


if( 0 < count($_POST['purchstat']) ){ //check at least one box was checked
$q="INSERT INTO table2purchstats (userid,purchstat_id)
VALUES";
foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
}
}

mysql_query($q, $link);
mysql_real_escape_string($userid),
mysql_real_escape_string($k);
}
}


I also noticed this:
if( 0 < count($_POST['purchstat'])

Does that mean that the code is looking for purchstat? I ask this because I don't see any indication that it's looking for a number in square brackets..

Unless this is looking for the numbers:
foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
}

SyCo
05-22-2008, 10:03 AM
you're running the query then sanitizing it. doh!

$q .= " (".mysql_real_escape_string($userid).",".mysql_real_escape_string($k)."), ";

You're still not trimming the last comma. You'll get a syntax error if you don't and not ids will insert.

Honestly, I have no idea what this is about.
name=purchstat[2]
if(isset($_POST['purchstat[3]'])) {
$purchstat_1 = $_POST['purchstat[1]'];

In the name 2 checkbox, if 3 is set make 1= a non post version of itself :confused:

Where is this fitting in to the rest of your code and why the mix of ids? Why set the value of the POST to a regular var? You can just use the POST vars.

SyCo
05-22-2008, 10:15 AM
Also you'll need to understand how foreach() works. Re-read my post 20 and any other foreach() tutorial you can find. foreach is the backbone of a lot of PHP scripts so you must understand it completely if you want any hope of coding well. Foreach() is used to loop through the values in an array and work with the array key/value pairs one at a time.

count is used to count the number of elements (key/value pairs) in an array

echo count($array_name);

will return a number if there are any elements in the array and false if the array is empty so it can be used in a conditional if().

Chazzl's method
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">

(Chazzl do you need the numbers in square brackets, or will they self assign if left blank?)

creates and array called $_POST['purchstat'] so you can count() it to see if any boxes were checked and foreach() it to extract the ids to insert.

Design-is-BS
05-22-2008, 10:17 AM
Where is this fitting in to the rest of your code and why the mix of ids? Why set the value of the POST to a regular var? You can just use the POST vars.

Sorry, SyCo

This is where they are:

name=purchstat[2] and if(isset($_POST['purchstat[3]'])) { on the document checkedboxes.php

if(isset($_POST['purchstat[2]'])) {
echo "
<tr>
<td valign=top><input type=checkbox {$check} name=purchstat[2] /></td>
<td>(b) the Business Development Bank of Canada incorporated under the Business Development Bank of Canada Act (Canada);</td>
</tr>";
} else {
echo "
<tr>
<td valign=top><input type=checkbox name=purchstat[2] /></td>
<td>(b) the Business Development Bank of Canada incorporated under the Business Development Bank of Canada Act (Canada);</td>
</tr>";
}


$purchstat_1 = $_POST['purchstat[1]']; is on the page abc_summary.php:

<?php
$purchstat_1 = $_POST['purchstat_[1]'];
$purchstat_2 = $_POST['purchstat_[2]'];
$purchstat_3 = $_POST['purchstat_[3]'];
$purchstat_4 = $_POST['purchstat_[4]'];
$purchstat_5 = $_POST['purchstat_[5]'];
$purchstat_6 = $_POST['purchstat_[6]'];
$purchstat_7 = $_POST['purchstat_[7]'];
$purchstat_8 = $_POST['purchstat_[8]'];
$purchstat_9 = $_POST['purchstat_[9]'];
$purchstat_10 = $_POST['purchstat_[10]'];
$purchstat_11 = $_POST['purchstat_[11]'];
$purchstat_12 = $_POST['purchstat_[12]'];
$purchstat_13 = $_POST['purchstat_[13]'];
$purchstat_14 = $_POST['purchstat_[14]'];
$purchstat_15 = $_POST['purchstat_[15]'];
$purchstat_16 = $_POST['purchstat_[16]'];
$purchstat_17 = $_POST['purchstat_[17]'];
$purchstat_18 = $_POST['purchstat_[18]'];
$purchstat_19 = $_POST['purchstat_[19]'];
$purchstat_20 = $_POST['purchstat_[20]'];
$purchstat_21 = $_POST['purchstat_[21]'];
$purchstat_22 = $_POST['purchstat_[22]'];
?>


On this page the checked boxes are posted form the original form (abc_agreement3.php and posted for review.

Basically my question was if I should keep the variables as $purchstat1 through $purchstat_22, instead of changing them into $purchstat[1] through $purchstat[22]?

Design-is-BS
05-22-2008, 10:18 AM
creates an array called $_POST['purchstat'] so you can count() it to see if any boxes were checked and foreach() it to extract the ids to insert.

Thank you, SyCo that makes perfect sense! :)

SyCo
05-22-2008, 10:26 AM
cool!

so I wanted to be sure I was talking sense so this is what i did to be sure I was getting what i would expect

<pre>
<?
print_r($_POST);
?>
</pre>
<br><br>
<form name="setup2" method="post">
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">
<input type="checkbox" name="purchstat[3]" value="foo">
<input type="submit">

Add that code on any PHP page click a couple of the boxes submit it and look at the resulting print_r() of the POST array. See how the multidimensional array is created

$_POST[purchstat][1] contains the value 'foo' (if 1 if checked).

That kind of simple debugging can take the guess work out of expected results.

another way to do it.
<pre>
<?
echo @$_POST[purchstat][1];
echo '<br>';
echo @$_POST[purchstat][2];
echo '<br>';
echo @$_POST[purchstat][3];
?>
</pre>
<br><br>
<form name="setup2" method="post">
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">
<input type="checkbox" name="purchstat[3]" value="foo">
<input type="submit">

Or using foreach (dont let this throw you if its confusing) I'm just adding it for completeness.
<br><br>
<pre>
<?
foreach($_POST as $k => $v){
//$v is the purchstat array so foreach it again
foreach($v as $k2 => $v2){
echo '<br>'.$k .'-'.$v.'-'.$k2 .'-'.$v2;

}
}
?>
</pre>
<br><br>
<form name="setup2" method="post">
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">
<input type="checkbox" name="purchstat[3]" value="foo">
<input type="submit">
</form>


so if you really feel the need to reassign the purchstat
array to non post vars you can foreach() it


<?
//$_POST is a multidimensional array
//$_POST['purchstat']is a normal array
foreach($_POST['purchstat'] as $k => $v){
$purchstat.'_'.$k=$k;
}
?>

which replaces
$purchstat_1 = $_POST['purchstat_[1]'];
$purchstat_2 = $_POST['purchstat_[2]'];
$purchstat_3 = $_POST['purchstat_[3]'];
$purchstat_4 = $_POST['purchstat_[4]'];
$purchstat_5 = $_POST['purchstat_[5]'];
$purchstat_6 = $_POST['purchstat_[6]'];
$purchstat_7 = $_POST['purchstat_[7]'];
$purchstat_8 = $_POST['purchstat_[8]'];
$purchstat_9 = $_POST['purchstat_[9]'];
$purchstat_10 = $_POST['purchstat_[10]'];
$purchstat_11 = $_POST['purchstat_[11]'];
$purchstat_12 = $_POST['purchstat_[12]'];
$purchstat_13 = $_POST['purchstat_[13]'];
$purchstat_14 = $_POST['purchstat_[14]'];
$purchstat_15 = $_POST['purchstat_[15]'];
$purchstat_16 = $_POST['purchstat_[16]'];
$purchstat_17 = $_POST['purchstat_[17]'];
$purchstat_18 = $_POST['purchstat_[18]'];
$purchstat_19 = $_POST['purchstat_[19]'];
$purchstat_20 = $_POST['purchstat_[20]'];
$purchstat_21 = $_POST['purchstat_[21]'];
$purchstat_22 = $_POST['purchstat_[22]'];

If you ever find yourself repeating near identical code, then there is a better way to do it!!

Design-is-BS
05-22-2008, 11:43 AM
You're still not trimming the last comma. You'll get a syntax error if you don't and not ids will insert.
//substr() off the final comma

I'm really sorry Syco, but I'm not sure what this means..

SyCo
05-22-2008, 12:01 PM
No need to apologize!

The loop will generate something like

(43,1),
(43,2),
(43,3),

but SQL doesnt want the final comma. it wants something like

(43,1),
(43,2),
(43,3)

so substr() will remove the final comma.

I usually try to differentiate words from functions by adding () so substr() is a PHP function. It's used to extract a sub-string from a string and can take the first, middle or end bits. Where ever you tell it. The php.net site has some great examples. So rather than do it for you I'll leave it for you to discover. If you have problems I'll give you a hand of course :)

search for substr in the function list on PHP.net and look at example #2 in particular.

Design-is-BS
05-22-2008, 12:09 PM
Like this:

foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
$q .= substr(" ($userid,$k)," -1, 1);
}

Chazzl
05-22-2008, 01:57 PM
Chazzl's method
<input type="checkbox" name="purchstat[1]" value="foo">
<input type="checkbox" name="purchstat[2]" value="foo">

(Chazzl do you need the numbers in square brackets, or will they self assign if left blank?)


Yep, they will self assign if left blank. Which is cool in some cases, but if that happened here then the options will kind of loose their identity... as in if I clicked the seventh checkbox in the HTML display, PHP is going to load it as checkbox[1] (purchstat[1] in this case).

Whereas, if we explicitly assign a a number to each, then when I click checkbox seven PHP will keep that id number and load purchstat[7].

Chazzl
05-22-2008, 02:09 PM
Like this:

foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
$q .= substr(" ($userid,$k)," -1, 1);
}
Almost!

substr("($userid,$k)," 0, -1);

This says (get) sub string starting from character zero all the way to negetive one from the last character (second to last).

Plus you are going to want to move the substring function outside of the loop.


foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
}
}
$q = substr( $q,-1, 1 );

Design-is-BS
05-22-2008, 02:17 PM
So this is my code now:


<?php

$user_username = $_REQUEST['username'];
$secsPurchased = $_REQUEST['secpurch'];
$aggreAmount = $_REQUEST['aggreamount'];
$date = date("d/m/y");
$termsConf = $_REQUEST['termsconfirm'];
$purchStatConf = $_REQUEST['accredinvestor'];
$subscrConf = $_REQUEST['subscriptconfirm'];

if($termsConf == 1 && $purchStatConf == 1 && $subscrConf == 1) {
$ABC_conf = "1";
} else {
$ABC_conf = "0";
}


if (isset($_REQUEST['username'])) {

//Check Connectivity
if(!is_resource($link)) {

echo "Failed to connect to the server\n";
// ... log the error properly

} else {
/* Obsolete
foreach($_POST as $key => $value){
if(preg_match("/purchstat_/",$key)){
$ids_to_insert[]=preg_replace"/purchstat_/","",$key);//remove purchstat_ leaving only the id
}
}
*/
if( 0 < count($_POST['purchstat']) ){ //check at least one box was checked
$q="INSERT INTO table2purchstats (userid,purchstat_id)
VALUES";
$userid = $_GET['username'];

foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= " ($userid,$k),";
}
}
$q .= substr( $q, 0, 1 );
$q .= " (".mysql_real_escape_string($userid).",".mysql_real_escape_string($k)."), ";
mysql_query($q, $link);
}

if (mysql_affected_rows() == 1) {
echo "success";
} else {
echo"failure";
}
}
}
?>

SyCo
05-22-2008, 02:56 PM
compare these two line
$q .= " ($userid,$k),";
and
$q .= " (".mysql_real_escape_string($userid).",".mysql_real_escape_string($k)."),

You have to read what mysql_real_escape_string() does and understand why it's used or all this isn't gong to help you. It's basic PHP/MySQL stuff and is the foundation of all web apps.

Download putty.exe
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

Echo $q after building it and run it in putty, see the errors and try to understand why you're getting them.

SyCo
05-22-2008, 02:57 PM
substr("($userid,$k)," 0, -1);

Oh Man! you told him!! lol, I could have done that!!! :rolleyes:

Chazzl
05-22-2008, 02:58 PM
<?php

$user_username = $_REQUEST['username'];
$secsPurchased = $_REQUEST['secpurch'];
$aggreAmount = $_REQUEST['aggreamount'];
$date = date("d/m/y");
$termsConf = $_REQUEST['termsconfirm'];
$purchStatConf = $_REQUEST['accredinvestor'];
$subscrConf = $_REQUEST['subscriptconfirm'];

if($termsConf == 1 && $purchStatConf == 1 && $subscrConf == 1) {
$ABC_conf = "1";
} else {
$ABC_conf = "0";
}

if (isset($_REQUEST['username'])) {

//Check Connectivity
if(!is_resource($link)) {

echo "Failed to connect to the server\n";
// ... log the error properly

} else {
if( 0 < count($_POST['purchstat']) AND isset($_GET['username']) AND !empty($_GET['username']) ){ //check at least one box was checked
$q = "INSERT INTO table2purchstats (userid,purchstat_id) \nVALUES";

$userid = preg_replace("'[[:punct:]]*'", '', $_GET['username']); // No punctuation allowd in the username
$userid = mysql_real_escape_string($userid); // mysql_real_escape_string() needs to be called before mysql_query()

foreach($_POST['purchstat'] as $k => $v){
if( is_numeric($k) ){
$q .= sprintf(" ($userid,%s),", mysql_real_escape_string($k) );
}
}
$q = substr( $q, 0,-1 );
// Uncomment this next line if you have trouble with your MySQL syntax.
//exit("<pre style='font:normal 10pt sans-serif;'>$q</pre>");
$sqlResult = mysql_query($q, $link) or die( __LINE__.' '.mysql_error() );
}

// Equal to 1 or should it be greater than zero?
//if ( 0 < mysql_affected_rows($sqlResult) ) {
if ( 1 == mysql_affected_rows($sqlResult) ) {
echo "success";
} else {
echo"failure";
}
}
}
?>

SyCo
05-22-2008, 03:07 PM
you got the -1 but not the $q .=substr :)

throwing sprintf() in at this point might just confuse.

Chazzl
05-22-2008, 03:15 PM
;) Keeps him on his toes.

SyCo
05-22-2008, 03:16 PM
lol, You on your toes here Brian??

Chazzl
05-22-2008, 03:21 PM
Link: sprintf — Return a formatted string (http://us2.php.net/sprintf)

Returns a string produced according to the formatting string format . In this case I used it to include the mysql_real_escape_string() within the $q string variable.

It's is the same exact effect of writing like this:


$q .= " ($userid,". mysql_real_escape_string($k) ."),";


It's useful for larger sql queries so that they are ledgable or easily readable.

For Example:

// MEMBER INFORMATION
$sqlQuery = sprintf("
INSERT INTO
members
SET
member_status = '%s',
member_number = '%s',
member_since = '%s',
member_since_month = '%s',
member_since_year = '%s',
member_registration = '%s',
business_name = '%s',
business_license = '%s',
business_address = '%s',
business_address2 = '%s',
business_city = '%s',
business_state = '%s',
business_zip = '%s',
business_physicalAddress = '%s',
business_physicalAddress2 = '%s',
business_physicalCity = '%s',
business_physicalState = '%s',
business_physicalZip = '%s',
business_phone = '%s',
business_fax = '%s',
business_website = '%s',
business_email = '%s',
business_tollfree = '%s'
WHERE
memberId = %s
",
mysql_real_escape_string( htmlspecialchars($_POST['member_status']) ),
mysql_real_escape_string( $_POST['member_number'] ),
mysql_real_escape_string( $_POST['member_since'] ),
mysql_real_escape_string( date('m', strtotime($_POST['member_since'])) ),
mysql_real_escape_string( date('Y', strtotime($_POST['member_since'])) ),
mysql_real_escape_string( @date('r') ),
mysql_real_escape_string( htmlspecialchars($_POST['business_name']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_license']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_address']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_address2']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_city']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_state']) ),
mysql_real_escape_string( $_POST['business_zip'] ),
mysql_real_escape_string( htmlspecialchars($_POST['business_physicalAddress']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_physicalAddress2']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_physicalCity']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_physicalState']) ),
mysql_real_escape_string( $_POST['business_physicalZip'] ),
mysql_real_escape_string( $_POST['business_phone'] ),
mysql_real_escape_string( $_POST['business_fax'] ),
mysql_real_escape_string( htmlspecialchars($_POST['business_website']) ),
mysql_real_escape_string( htmlspecialchars($_POST['business_email']) ),
mysql_real_escape_string( $_POST['business_tollfree'] ),
mysql_real_escape_string( $intMemberId )
);


This way the code is vertical rather than horizontal. It's better to scroll up and down than left to right.

Design-is-BS
05-24-2008, 08:37 AM
OK guys, I have a different problem with this configuration now. For some reason whenever I go to check off the boxes for testing, the summary page displays all of the boxes unchecked. Before it would only display the boxes that are checked and no other boxes.

I'm going to PM you my FTP information. The pages you need to take a look at are:

abc_agreement3.php
abc_summary.php
checkedboxes.php
congrats.php

Design-is-BS
05-26-2008, 09:47 AM
*bump*

SyCo
05-27-2008, 09:21 AM
The forum is for open sharing of ideas. Looking at your code on your server won't help anyone else with the same problem.

Design-is-BS
05-27-2008, 10:23 AM
I decided to take the easy way out.

I used the table "table2purchstats" and simply give it a field for id, purchstat_a thorugh purchstat_v, and date_completed.

I'll probably come back to this one day, but my client just wants it to work.

Thanks SyCo.

SyCo
05-27-2008, 10:30 AM
That's cool, whatever works for you.

Flemming
02-10-2009, 01:00 PM
I am doing the same thing as above but doesn't work. What is wrong with this code?
<?php
require('db_connect.php');

$General_Equivalency_Diploma = $_POST['highestdegree_1'];
$High_School_Diploma = $_POST['highestdegree_2'];
$Trade_Certificate = $_POST['highestdegree_3'];
$Associates_Degree = $_POST['highestdegree_4'];
$Bachelors_Degree = $_POST['highestdegree_5'];
$Masters_Degree = $_POST['highestdegree_6'];
$Doctoral_Degree = $_POST['highestdegree_7'];
$Other = $_POST['highestdegree_8'];
$Other_txt = $_POST['highestdegree_9'];

//$myarray = array("Foos","Bars","Bazzes");

foreach($_POST as $key => $value){
if(preg_match("/highestdegree_/",$key)){
$ids_to_insert[]=preg_replace"/highestdegree_/","",$key);//remove highestdegree_ leaving only the id
}
}

if(count($ids)>0){ //check at least one box was checked
$q="INSERT INTO NedasiStats (Stats_ID,checked)
VALUES";

foreach($ids as $v){
$q.=' ('.$userid.','.$v.'),';
}
//substr() off the final comma

//insert statement within count if()
}
?>

Chazzl
02-12-2009, 02:20 PM
Heyas Flemming,

I'm not able to give much advice based on what information is provided, but there are a couple parentheses missing that might be giving you trouble.

Also, $userid is undefined unless it is set inside db_connect.php.

<?php
require('db_connect.php');

foreach($_POST as $key => $value) {

if(preg_match("/highestdegree_/", $key)) {
//remove highestdegree_ leaving only the id
$ids_to_insert[] = str_replace("/highestdegree_/", "", $key);
}
}

//check at least one box was checked
if(count($ids_to_insert) > 0) {
$query = "INSERT INTO NedasiStats (Stats_ID, checked) VALUES";

foreach($ids as $values){
$query .= ' (' . $userid . ',' . $values . '),';
}

//substr() off the final comma

//insert statement within count if()
}
?>

— Chazzl