I have an online form which collects member(s) information and stores it into a very long MySQL database. We allow up to 16 members to enroll at a single time and originally structured the DB to allow such.
For example:
If 1 Member enrolls, his personal information (first name, last name, address, phone, email) are stored on a single row.
If 15 Members enroll (all at once), their personal information are stored in the same single row.
The row has information housing columns for all 'possible' inputs. I am trying to consolidate this code and having every nth member that enrolls put onto a new record within the database.
I have seen sugestions before for inserting multiple records as such:
INSERT INTO tablename VALUES
(('$f1name', '$f1address', '$f1phone'), ('$f2name', '$f2address', '$f2phone')...
The issue with this is two fold:
I do not know how many records are
being enrolled from person to person
so the only way to make the
statement above is to use a loop
The information collected from the
forms is NOT a single array so I
can't loop through one array and
have it parse out. My information is
collected as individual input fields
like such: Member1FirstName,
Member1LastName, Member1Phone,
Member2Firstname, Member2LastName,
Member2Phone... and so on
Is it possible to store information in separate rows WITHOUT using a loop (and therefore having to go back and completely restructure my form field names and such (which can't happen due to the way the validation rules are built.)
If you form's structured so that all the fields are numbered properly, so that a "firstname #1" is matched up with all the other "#1" numbered fields, then a loop is the simplest solution.
start_transaction();
$errors = false;
for ($i = 1; $i <= 16; $i++) {
if (... all $i fields are properly filled in ...) {
$field = $_POST["field$i"];
$otherfield = $_POST["otherfield$i"];
etc...
... insert into database ...
} else {
... handle error condition here
$errors = true;
}
}
if (!$errors) {
commit_transaction();
} else {
rollback();
}
If they're numbered randomly, so that firstname1 is matched with lastname42 and address3.1415927, then you'd have to build a lookup table to map all the random namings together, and loop over that
followup per comment:
well, if you absolutely insist on maintaining this database structure, where each row contains 16 sets of repeated firstname/lastname/etc.. records, then you'd do something like this:
$first = true;
for ($i = 1; $i <= 16; $i++) {
if (fields at position $i are valid) {
$firstname = mysql_escape_real_string($_POST["F{$i}name"]);
$lastname = mysql_real_escape_string($_POST["F{$i}lastname"]);
if ($first) {
$dbh->query("INSERT INTO table (f{$i}name, f{$i}lastname) VALUES ($firstname, $lastname);"
$recordID = $dbh->query("SELECT last_insert_id();");
$first = false;
} else {
$dbh->query("UPDATE table SET f{$i}name=$firstname, f{$i}lastname=$lastname WHERE idfield=$recordID");
}
}
}
It's ugly, but basically:
loop through the form field sets until you find a valid set (all required fields filled in, valid data entered, etc..
Insert that data set into the database to create the new record
retrieve ID of that new record
continue looping over the rest of the fields
for every subsequent set of valid records, do an update of the previously created record and add in the new fieldset data.
Though, honestly, unless you've got some highly offbeat design need to maintain a single table with 16 sets of repeated columns, you'd be better off normalizing a bit, and maintain two seperate tables. A parent "enrollment" table, and a child "members" table. That way you can create the parent enrollment table, then just insert new children as you encounter them in the form.
update #2:
well, a simplified form of a normalized layout would be:
signups (id, name, etc...)
signup_members (id, signup_id, firstname, lastname)
and you'd pull the full signup record set with the following query:
SELECT signups.id, signups.name, signup_members.id, firstname, lastname
FROM signups
LEFT JOIN signup_members ON signups.id = signup_members.signup_id
ORDER BY ...
That would give you a series of rows, one for each 'member' signup. To build the CSV, a simple loop with some state checking to see if you've reached a new signup yet:
$oldid = null;
$csv = ... put column headers here if you want ...
while ($signup = $result->fetchrow()) {
if ($signup['signups.id'] != $oldid) {
// current signup doesn't match previous seen id, so got a new signup record
$csv .= "\n"; // start new line in CSV
$csv .= ... add first few columns to new csv row ...
$oldid = $signup['signups.id']; // store new record id
} else {
$csv .= ... add extra member columns to current csv row ...
}
}
What you're trying to do could be simpler, but to solve the problem, you can join the user information into one variable, separated by a char of your choice and send it to Mysql DB...
$user1 = $f1name . ';' . $f1address . ';' . $f1phone;
$user2 = $f2name . ';' . $f2address . ';' . $f2phone;
$user3 = $f3name . ';' . $f3address . ';' . $f3phone;
INSERT INTO table-name VALUES('$user1','$user2','$user3')
To extract, just "explode" the value by the ";".
If you use the same order for all users data, and if you send a verification string in case one user leaves a field blank, works just fine :)
humm... this work's just fine if the user isn't allowed to use ";" as "personal data" :)
Hope it helps U!
I think you might want to look at "variable variables":
http://php.net/manual/en/language.variables.variable.php
Then you could conceivably loop through from 1 to 15, without having to rename your form fields.
Related
So, I've been looking for a solution to my case, but I've kept finding only partial and not quite solving-the-matter kind of answers.
First, let me describe what I'm trying to achieve.
In my database I have two tables: PLACES and PLACES_CATEGORIES which are connected by a third table PLACES_A_CATEGORIES in an entity many to many. That is because a PLACE can be characterised by one or more CATEGORIES (but it can also have no CATEGORIES at all).
I want to add data send in one form to two tables: PLACES and PLACES_A_CATEGORIES. The user has all the categories listed with checkboxes and he may (but doesnt have to) check one or more of them.
I automated the display of those checkboxes so it reacts accordingly to changes in database (like adding or removing categories). This part works just fine, but let me show the code for you as it may be useful in solving the real issue:
$query = "SELECT name FROM places_categories";
$result = $connection->query($query);
$category_no = $result->num_rows;
echo "Categories of places:";
for ($j = 0; $j < $category_no; ++$j)
{
$category = $result->fetch_assoc()['name'];
echo '<br><input type="checkbox" id="'.$category.'" name="places_categories" value="'.$category.'"><label for="'.$category.'">'.$category.'</label><br>';
}
So, let's return to the problem. I want to:
always add data (only one row) to the table PLACES
add as many rows of data to the table PLACES_A_CATEGORIES as many checkboxes have been checked
So, let me now show you how I've tried to solve the matter and below I'll explain what and why I've done.
if ($everything_OK==true)//Hurra, everything is ok, lets add the place to the database
{
mysqli_query($connection, "SET NAMES utf8");//need it for special characters
//Adding multiple rows of data to database
$query = "SELECT name FROM places_categories";
$result = $connection->query($query);
$category_no = $result->num_rows;
for ($j = 0; $j < $category_no; ++$j)
{
$category[$j] = $result->fetch_assoc()['name'];
if ($_POST['places_categories'] == $category[$j])
{
//counts number of records in table PLACES
$query1 = "SELECT name FROM places";
$result1 = $connection->query($query1);
$places_no = $result1->num_rows;
$places_no += 1;
//looks for category_id in table places_categories where the name matches the current value from form
$query2 = "SELECT category_id FROM places_categories WHERE name='$category[$j]'";
$result2 = $connection->query($query2);
$what_category_id = mysqli_fetch_array($result2);
$connection->query("INSERT INTO places_a_categories VALUES ('$places_no', '$what_category_id')");
}
}
if ($connection->query("INSERT INTO places VALUES (NULL, 0, 0, 0, '$name', '$wysokosc', '$zajawka', '$zatloczenie', '$data_dodania', '$data_edycji', '$szer_geo', '$dlu_geo', '$tytul', '$opis', '$adres', '$tresc')"))
{
echo "Test!";
}
else
{
throw new Exception($connection->error);
}
}
Okay, explanations:
The part which inserts data to the table PLACES works just fine. It
adds data to the database according to what user has added in a form.
No help needed here.
Because of the before-mentioned automation of
table CATEGORIES I want to check how many of categories actually are
in the database. The first part of the code was supposed to do this.
with instruction FOR I assign every existing category to an array with a value equal to the name of the category in the database
then with instruction IF I want to add ass many rows of data to the table PLACES_A_CATEGORIES as many checkboxes have been checked
first value $places_no equals to id of the place which is being added to another table
second value $what_category_id looks for category_id in table PLACES_CATEGORIES where the name matches the current value got from the checkbox
And what are the results? Data is added to the table PLACES with no problem at all. But there is nothing added to the second table. Furthermore, I get no error message of any kind. It's probably some stupid error I just can't see... Any ideas? What have I done wrong?
So I have a form that lets people add a list of grades, and using jQuery they are able to add up to 9 extra fields. (Meaning they can submit any number from 1 to 10 grades). What I want to know is how I can go about storing this in my database, as I do not want to convert them all into one string. My concern is that because I don't know how many grades the user is going to enter, I can't set a definitive array number to store (or can I?)
Sorry if this is not terribly well explained, I'm still relatively new to PHP and SQL!
A quick assumption if I am not mistaken would be: saving one user with multiple grades for multiple subjects can be achieved like this.
Firstly we get one user id from the form and put it in PHP:
$id = isset($_POST['id'])? $_POST['id']:'';
Then get multiple grades and subjects which would be sent as comma separated values:
//$id= explode(',',$_POST['id']);// For multiple users
$grade= explode(',',$_POST['grade']);
$subj= explode(',',$_POST['subject']);
$entry= explode(',',$_POST['entry']);
Now count the number of grades: $count= count($grade);
Use the count in a for loop to have insert in loop:
for ($i = 0; $i < $count; $i++) {
try {
$dbh->beginTransaction(); //$dbh is your PDO connection
$insertQ = "INSERT INTO `grades` (id, grade, subject, entry)
VALUES('$id', '$grade[$i]', '$subj[$i]','$entry[$i])";
$dbh->query($insertQ);
$dbh->commit();
} catch (Exception $e) {
$error = $e->getMessage();
}
}
Hope this may help.
I am having an issue. I have a bunch of inputs that share the same name. This creates arrays which are placed into the database and that all works fine but I am having a major dilemma in trying to keep the blank rows of inputs from creating blank entries in the database table.
The code is as such:
foreach($_POST['datetime'] as $dbrow=>$startdate) {
if(isset($_POST['def'])) {
$start = $startdate;
$abc = $_POST['abc'][$dbrow];
$def = $_POST['def'][$dbrow];
$ghi = $_POST['ghi'][$dbrow];
$db_insert = "INSERT INTO tablename (start, abc, def, ghi) VALUES('$start', '$abc', '$def', '$ghi')";
This is fine and dandy but I cant get the if statement to work. The form that is using POST to get the users information has 5 rows of inputs each with fours columns (start, abc, def, ghi). If I enter data in the form and submit it, then all the data goes to the database (yay - success), if I only enter the data in rows 1-4 then the database still enters 5 rows of data. What am I doing wrong?
---------------------EDIT---------------------
Ok so upon a deeper look what appears to be happening is the code keeps wanting to submit ALL of rows of dynamically generated inputs whether they contain content or not. So I devised the following code:
$db_tur = count(array_filter($start_date));
for($db_total_used_rows=0;$db_total_used_rows<=$db_tur;$db_total_used_rows++){
$db_start_date = $_POST['datetime'][$db_total_used_rows];
$db_abc = $_POST['abc'][$db_total_used_rows];
$db_def = $_POST['def'][$db_total_used_rows];
$db_ghi = $_POST['ghi'][$db_total_used_rows];
}
$db_insert = .....;
In theory what this does is $db_tur counts up all of the inputs being used under the start_date variable. I then break it into a count array which should be able to be used as $db_total_used_rows. However this doesnt seem to be limiting the total number of rows of inputs being inserted into the database. So I guess its back to the drawing board unless someone else has a better idea of how to accomplish this. I'm so ready to give up right now.
Use this loop structure:
foreach ($_POST['datetime'] as $dbrow => $start) {
$abc = $_POST['abc'][$dbrow];
$def = $_POST['def'][$dbrow];
$ghi = $_POST['ghi'][$dbrow];
if (!empty($abc) && !empty($def) && !empty($ghi) && !empty($start)) {
$db_insert = ...;
...
}
}
You could change && to || if it's OK for the user to leave some of the fields blank -- it will only skip rows where all fields are blank.
Except for checkboxes, all form fields will POST, even when empty. So if def is a text box it will always be present in your POST. A better test would be
if(!empty($_POST['def'])) {
I have a form where I am trying to implement a tag system.
It is just an:
<input type="text"/>
with values separated by commas.
e.g. "John,Mary,Ben,Steven,George"
(The list can be as long as the user wants it to be.)
I want to take that list and insert it into my database as an array (where users can add more tags later if they want). I suppose it doesn't have to be an array, that is just what seems will work best.
So, my question is how to take that list, turn it into an array, echo the array (values separated by commas), add more values later, and make the array searchable for other users. I know this question seems elementary, but no matter how much reading I do, I just can't seem to wrap my brain around how it all works. Once I think I have it figured out, something goes wrong. A simple example would be really appreciated. Thanks!
Here's what I got so far:
$DBCONNECT
$artisttags = $info['artisttags'];
$full_name = $info['full_name'];
$tel = $info['tel'];
$mainint = $info['maininst'];
if(isset($_POST['submit'])) {
$tags = $_POST['tags'];
if($artisttags == NULL) {
$artisttagsarray = array($full_name, $tel, $maininst);
array_push($artisttagsarray,$tags);
mysql_query("UPDATE users SET artisttags='$artisttagsarray' WHERE id='$id'");
print_r($artisttagsarray); //to see if I did it right
die();
} else {
array_push($artisttags,$tags);
mysql_query("UPDATE users SET artisttags='$artisttags' WHERE id='$id'");
echo $tags;
echo " <br/>";
echo $artisttags;
die();
}
}
Create a new table, let's call it "tags":
tags
- userid
- artisttag
Each user may have multiple rows in this table (with one different tag on each row). When querying you use a JOIN operation to combine the two tables. For example:
SELECT username, artisttag
FROM users, tags
WHERE users.userid = tags.userid
AND users.userid = 4711
This will give you all information about the user with id 4711.
Relational database systems are built for this type of work so it will not waste space and performance. In fact, this is the optimal way of doing it if you want to be able to search the tags.
I have 4 tables named wheels, tires, oil_change, other_servicing.
Now, I have an order form for the person that comes for a car checkup. I want to have all of these 4 options in a form. So say someone comes for new wheels but not for tires, oil change, and other servicing and they will leave the other fields blank. And then you might have a scenario where all four fields are filled up. So how do i submit each to their respective tables from that one form?
The form will submit to a single php script. In the php you must do 4 separate queries to put the data into the correct tables. For example if you have this in php:
$wheels = $_REQUEST['wheels'];
$tires = $_REQUEST['tires'];
$oil_ch = $_REQUEST['oil_change'];
$other = $_REQUEST['other_servicing'];
mysql_query("INSERT INTO wheels (wheels) VALUES $wheels");
mysql_query("INSERT INTO tires (tires) VALUES $tires");
mysql_query("INSERT INTO oil_change (oil_change) VALUES $oil_ch");
mysql_query("INSERT INTO other_servicing (other_servicing) VALUES $other");
Of course I don't know the schemas of your tables but this is just an example of how you have to split it into 4 queries.
However, I would suggest to you that rather than have 4 tables for this, just have one table and make each of these a column instead. There may be other details I don't know about which would necessitate separate tables but with the info you have given seems like it would be simpler.
This shouldn't present any problem. The PHP page that receives the form data can run as many queries as you want. The skeleton for the code would be something like:
if($_POST['wheels']) { //if they filled in the field for wheels...
mysql_query("insert into wheels...");
}
if($_POST['tires']) { //if they filled in the field for tires...
mysql_query("insert into tires...");
}
if($_POST['oil_change']) { //if they filled in the field for oil_change...
mysql_query("insert into oil_change...");
}
... etc
for each form you would have something like this:
if($_POST['wheels']){mysql_query("INSERT INTO wheel_table (column1) VALUES (" . 'mysql_real_escape_string($_POST['wheels']) . "')")
this checks if the form element has been set, or has a value, and if it does, it creates a new row in the corresponding table.
if the form element's name is not 'wheels', you'll have the change $_POST['wheels'] to $_POST['form_element_name'] and if the table's name is not wheel_table, you'll have to change that and same with the column name.
this all has to be wrapped in a
In the form action you will specify the php file that will process the form.
In the php script file you will make tests of what parts of the forms are used and inserted in the respective table.
Try to separate the tests and the inserts of each table, to be easier for you.
This could be useful
if(isset($_POST['submit'])) // assuming you have submit button with name 'submit'
{
$fields['wheels'] = isset($_POST['wheels']) ? $_POST['wheels'] : null;
$fields['tires'] = isset($_POST['tires']) ? $_POST['tires'] : null;
$fields['oil_change'] = isset($_POST['oil_change']) ? $_POST['oil_change'] : null;
$fields['other_servicing'] = isset($_POST['other_servicing']) ? $_POST['other_servicing'] : null;
$q="";
foreach($fieldsas $key=>$val)
{
if($val!==null)
{
$q="insert into ".$key." values('".mysql_real_escape_string($val)."')";
mysql_query($q);
}
}
if($q==="") echo " Please fill up at least one field !";
}
This is just the core idea, using this you can execute multiple queries if user submits more than one fields at once and you may have to add other values (i.e. user_id).