Mail Dynamic Table with Forms via PHP - php

I have an order form (table) that I need to be sent to an email address.
I understand the basics of how to send an email in PHP, but not the specifics
of this situation (taking the information of the cookie array + form elements and put them in body of the PHP mailer)
I am using this link's answer to store the order form as an array in a cookie
Then I use this javascript to create the table in HTML, inside the #catalog div. The important part is the for loop that makes the table. Using list.items(); one can list the "cookie array" as an array
function loopArrayMail() {
if ($.cookie('productWishlist') == null) {
html = ""; $('#catalog').html(html);
} else {
var cookie = $.cookie("productWishlist"); var items = cookie ? cookie.split(/,/) : new Array();
var html = "<table><tr><th>Product</th><th># to order</th></tr>";
for(var i=0;i<items.length;i++){ html += "<tr><td width='450'>"+items[i]+"</td><td><input type='text' name='numberOfItems' /></td></tr>"; }
html += "</table>"; $('#catalog').html(html);
}}
There is a text input next to each item in the order form for the user to input the # of items they want.
How would I send the contents of the table and each form input as an email in PHP?
My guess is that I'd have to take the cookie array, and with each iteration have an array of all the text inputs and use foreach so that they are together in the email (unsure of how to do this exactly). It is also important that there can be any number of text inputs as the number of items on the order form will increase/decrease.
Here is an example of using foreach to get multiple input boxes, but how might I combine the array from my cookie with the text inputs?

Better you send only plain HTML in the email without any javascript because you won't have any javascript in the email program nor you have any cookies.
No idea who told you you could use that, but Email programs are not Browsers.
However if you send a link via email, any user can then open it in a full-featured internet browser so this might be what you're looking for.
Netscape Communicator 4 had support for javascript in emails, no idea about the cookies.

First you must give the form elements a name followed by [] indicating that it is an array, when you create the form elements in the loopArrayMail() function.
for(var i=0;i<items.length;i++){
html += "<tr><td width='450'>"+items[i]+"</td><td><input type='text' name='ordernum[]' size='8' /></td></tr>";
}
Since the cookie is a string you must first explode the string based on the delimiter which is a comma. Place the two arrays into variables. Then use a for loop to go through all of the array.
function explode_trim($str, $delimiter = ',') {
if ( is_string($delimiter) ) {
$str = trim(preg_replace('|\\s*(?:' . preg_quote($delimiter) . ')\\s*|', $delimiter, $str));
return explode($delimiter, $str);
}
return $str; }
$orderCookie = explode_trim($_COOKIE['productWishlist']);
$orderNum = $_POST['ordernum'];
for ( $i = 0; $i < count($orderCookie); $i++) {
echo $orderCookie[$i] . ' = ' . $orderNum[$i] . '<br />';
}

Related

Selectize.js doesn't read HTML entities correctly

I'm working with Selectize.js currently and am stuck on a problem relating to HTML entities not displaying correctly in Selectize fields, and therefore failing checks after submission. We use PHP on the backend and run every Selectize option through htmlspecialchars($option);. We then export the PHP array to a JSON array in preparation for adding it to the Selectize script/field.
//Array of options
$options = getOptions();
$optionsArray = array();
foreach($options as $item) {
$optionsArray[] = array('text' => htmlspecialchars($item), 'value' => htmlspecialchars($item));
}
//Create html script to run selectize initialization
$htmlcode = "<script>";
...
$htmlcode .= "var optionList = " . json_encode($"optionsArray") . ";";
$htmlcode .= "$('#selector').selectize({ options: optionList });";
...
$htmlcode .= "</script>";
The point here is to protect against malicious entries by encoding. This typically wouldn't be a problem, as browsers will detect the entities and convert them automatically (ie. will detect & and display as &. However, that is NOT happening inside the selectize. As you can see in the image below, outputting an option with an ampersand displays correctly on the page, but it doesn't display accurately in the Selectize field.
Example:
The problem then becomes larger, as we are comparing the selected item against the database after submission, to ensure that the selected entry actually exists. If the entry testOption&stuff actually exists, the form submission will check testOption&stuff against it, and will obviously fail the check.
//For simplicity, checking against static option
var $selectedOption = $_POST["options"];
if ($selectedOption == "testOption&stuff") {
//Do success
} else {
//Do failure
}
How can I resolve this and make it so that the Selectize field will store and display the correct entry (ie. &)?
Thanks!

php email current page

I have made an ordering system that right now goes from the product form to a review page. I have the page set up to use PHP loops to show what products they selected form the prior page and it works great. Now I need to have a "order" button that emails the order on. I the practice of writing less code, I would like to not have to re write all the code to email this form on another php form. Is there a way to have email headers on this page and dump the generated html into the body of the email to send?
Here is how I loop the form contents from the previous page. Basically it goes though all the products and if its there, show them on the review. If not, dont.
for ($i=0; $i<8; $i++) {
if (!empty($_REQUEST['driver'][$i]['select'])) {
//add the club to the total of clubs
$club = $_REQUEST['driver'][$i]['select'];
array_push($club_total, $club);
//add the price to the cost
list($shaft, $price) = explode(":", $_REQUEST['driver'][$i]['shaft']);
array_push($cost, $price);
//show the user
echo '<h3>' .$_POST['driver'][$i]['name']. ' - $'. money_format('%i', $price).'</h3>';
echo '<ul>';
if (!empty($_REQUEST['driver'][$i]['left'])) {
echo '<li><strong>Left Handed</strong></li>';
}
echo '<li>Length: '.$_POST['driver'][$i]['length']. '"</li>';
echo '<li>Shaft: '.$shaft. '</li>';
if (!empty($_REQUEST['driver'][$i]['hossel'])) {
echo '<li>Purist Hossel: ' .$_POST['driver'][$i]['hossel'].'</li>';
}
if (!empty($_REQUEST['driver'][$i]['color'])) {
echo '<li>Purist Color: ' .$_POST['driver'][$i]['color'].'</li>';
}
echo '</ul>';
}
You could capture your html in the output buffer, then store it in a variable for later use (as in, putting it into the body of an email).
ob_start();
for ($i=0; $i<8; $i++) {
// ... your code
}
$my_html = ob_get_contents();
ob_end_clean();
then put $my_html as your email body and send it along.
The idea of putting it all in a variable the first time around also works, but this might save you some effort of rewriting everything.
Instead of echoing out the html, build up a string, so $out .= "your html" etc, then you can easily set that lump of html to the body of the email function.
I am assuming you know how to code that, else I'll add code example for you.

Using For loop to get values of multiple elements in PHP

The title is so general mainly because I don't know what should be the appropriate title for it. Let me just explain the situation:
Say that I have two textboxes named LastName0 and FirstName0 and a button called addMore. When I click addMore, another two textboxes will be created through JavaScript. These textboxes will be named LastName1 and FirstName1. When I click the addMore button again, another two textboxes button will be created and named LastName2 and FirstName2 respectively. This will go on as long as the addMore button is clicked. Also, a button named deleteThis will be created alongside the textboxes. This simply deletes the created textboxes when clicked.
I also initialized a variable called counter. Every time the addMore button is clicked, the counter goes up by 1, and whenever the deleteThis button is clicked, the counter decreases by 1. The value of the counter is stored in a hidden input type.
When the user submits the form, I get the value of the counter and create a For loop to get all the values of the textboxes in the form. Here is the sample code:
//Suppose that the user decides to add 2 more textboxes. Now we have the following:
// LastName0 FirstName0
// LastName1 FirstName1
// LastName2 FirstName2
$ctr = $_POST['counter']; //the counter == 3
for ($x = 0; $x < $ctr; $ctr++)
{
$lastname = $_POST["LastName$x"];
$firstname = $_POST["FirstName$x"];
//This will get the values of LastName0,1,2 and FirstName0,1,2
//code to save to database…
}
On the code above, if the value of counter is equal to 3, then the values of textboxes LastName0,1,2 and FirstName0,1,2 will be saved. Now here is the problem: If the user decided to delete LastName1 and FirstName1, the For loop will not be able to iterate properly:
$ctr = $_POST['counter']; //the counter == 2
for ($x = 0; $x < $ctr; $ctr++)
{
//Only LastName0 and FirstName0 will be saved.
$lastname = $_POST["LastName$x"];
$firstname = $_POST["FirstName$x"];
//code to save to database…
}
Someone told me to use the "push and pop" concept to solve this problem, but I am not really sure on how to apply it here. So if anyone can tell me how to apply it, it'll be grand.
Add your input text boxes with name as array ie, <input type="text" name="FirstName[]" />
In php you can fetch them as a array. ie,
foreach($_POST["FirstName"] as $k=>$val){
echo $val; // give you first name
echo $_POST["LastName"][$k]; // will give you last ame
}
In this case even if one set of field is removed in HTML will not affect the php code.
One solution would be to use the isset function like this:
$ctr = $_POST['counter'];
for ($x = 0; $x < $ctr; $ctr++)
{
isset($_POST["LastName$x"])?$lastname = $_POST["LastName$x"]:;
isset($_POST["FirstName$x"])?$firstname = $_POST["FirstName$x"]:;
}
If it is possible, instead of using LastNameN and FirstNameN names try using LastName[N] and FirstName[N], this way the result is an array and you can iterate through it with a foreach, meaning you will not need the counter and the index of the value will not be important:
foreach ($_POST["LastName"] as $i=>$lastname) {
if (!isset($_POST["FirstName"][$i])) {
// This should only happen if someone messes with the client side before posting
throw new Exception("Last name input does not have a related First name input");
}
$firstname = $_POST["FirstName"][$i];
}
If not, then you may have to use your $counter in a different way
$current = 0;
while ($counter) { // Stop only when i found all
if (isset($_POST["LastName$current"]) {
$counter--; // Found one
$lastname = $_POST["LastName$current"];
$firstname = $_POST["FirstName$current"];
}
$current++;
}
A better way to solve this would be to use arrays for Firstname and Lastname. Instead of calling them Lastname0 and Firstname0, then Lastname1 and Firstname1, call them all Lastname[] and Firstname[]. Give them ID's of Lastname0 and Firstname0 and so on for the delete function, but keep the names as arrays.
When the form is submitted use the following:
foreach($_POST['Lastname'] as $i => $lastname) {
$firstname = $_POST['Firstname'][$i]
//... code to save into the database here
}
Be warned though that in IE if you have an empty field it will not be submitted, so if Lastname0 has a value, but Firstname0 does not, then $_POST['Firstname'][0] will in fact contain the value of Firstname1 (assuming it has a value in it). To get around this you can use javascript to check if a field is empty when submitting the form, and if so put the word EMPTY in it.
Do not use counter if not required
A much easier way is to add array name when admore clicked.
Give a name like first_name[] in textbox
if you create form like that you can use foreach through $_POST['first_name']
try var_dump($_POST) in you php code to see how things goes on.
Inside your for loop, maybe you could try...
if ((isset($_POST["LastName$x"])) && (isset($_POST["FirstName$x"]))){
$lastname = $_POST["LastName$x"];
$firstname = $_POST["FirstName$x"];
//code to save to database…
}
This will check if the variables exists before you try to do anything with them.

php processing a dynamically generated form

I'm using php to generate an html page that displays blog/thread items, and I am using javascript to show/hide some of the details. The problem is that I am generating unique IDs for each set of hidden content, which contains a form to process the input. In processing the form, I need to know which blog item was edited - I want to use $_POST. I'm pretty new to javascript, and I'm thinking that there is probably a solution I can use there.
I want the post to save the text to the mysql database (so call one of my php functions that I have working) and tell me what the text was and what the threadId is.
Here is the php code snipet, where $threadDetailItem is an array that has my thread data in it.
foreach ($threadData as $threadDetailItem)
{
// display main line (a bunch of code here ...)
// append button to edit or delete the post for admin
if ( isset ($_SESSION['isAdmin']) && $_SESSION['isAdmin'] == 'Y'){
// edit link opens content, and delete pops up a confirmation box
$el = sprintf ("editThreadLink_%d", $threadDetailItem['blogThreadId']);
$ec = sprintf ("editThreadContent_%d", $threadDetailItem['blogThreadId']);
$link1 = sprintf ("<a id=\"%s\" href=\"javascript:toggle('%s', '%s');\">+</a>", $el, $ec, $el);
$msg .= sprintf ("<li id=\"field6\">%s</li>\n", $link1);
}
$msg .= "</ul>\n";
echo $msg;
// now that the row is printed, lets add the hidden content if admin so they can edit
if ( isset ($_SESSION['isAdmin']) && $_SESSION['isAdmin'] == 'Y'){
// hidden content to enable editing of the posting
$msg = sprintf ("<div id=\"%s\" style=\"display: none\">\n", $ec);
echo $msg;
echo "<form name=\"form\" method=\"post\" action=\"\">\n";
$msg = sprintf ("<textarea id=\"%s\" name=\"%s\">%s</textarea>\n",
$ec, $ec, $threadDetailItem['threadTitle']);
echo $msg;
$msg = sprintf ("<button type=\"submit\"> %s</button>\n", $lang->get('BLOG POST'));
echo $msg;
echo "</form>\n";
echo "</div>";
}
}
Suggestions on good ways to handle this event are much appreciated. Thanks in advance.
The fields in the data are: blogThreadId, threadTitle, username, createdOn, lastUpdated, displayed (not used) and threadDetails (array containing the posting information).
I was able to use $_POST along w/ the ID in a hidden field to enable my php scripts to know which thread was being edited. It is working

checkbox's stay checked after pagination in php

Hello i want any checkbox i am gonna check, to stay checked after pagination.
here is the code:
foreach($test as $string){
$queryForArray = "SELECT p_fname,p_id FROM personnel WHERE p_id = " .$string["p_id"]. " ;" ;
$resultForArray = mysql_query($queryForArray, $con);
$rowfForArray = mysql_fetch_array($resultForArray);
?>
<td id="<?php echo $rowfForArray["p_id"]?>" onclick="setStyles(this.id)" ><?php echo $rowfForArray["p_fname"]?></td>
<td><input id="<?php echo $rowfForArray["p_id"]?>" class="remember_cb" type="checkbox" name="how_hear[]" value="<?php echo $rowfForArray["p_fname"]?>"
<?php foreach($_POST['how_hear'] as $_SESSION){echo (( $rowfForArray["p_fname"] == $_SESSION) ? ('checked="checked"') : ('')); } ?>/></td>
</tr>
<tr>
I am geting the data from a search result i have in the same page , and then i have each result with a checkbox , so that i can check the "persons" i need for $_Session use.
The only think i want is the checkbox's to stay checked after pagination and before i submit the form!(if needed i can post the pagination code, but he is 100% correct)
In the checkbox tag use the ternary operation, without that foreach inside him:
<input [...] value="<?php echo $rowfForArray["p_fname"]?>" <?php $rowfForArray["valueToCompareIfTrue"] ? "checked='checked'" : ''; ?> />
because the input already is inside of 'for' loop, then each time of the loop will create a new checkbox wich will verify if need to being check or not.
I hope I have helped you.
A few ways to tackle this:
(Straight up PHP): Each page needs to be a seperate form then, and your "next" button/link needs to submit the form everytime they click next. The submit data should then get pushed to your $_SESSION var. The data can then be extracted and used to repopulate the form if they navigate backwards as well. Just takes some clever usage of setting the URL with the proper $_GET variables for the form.
(HTML5): This will rely more on JavaScript, but basically you get rid of pagination and then just break the entire data set into div chunks which you can hide/reveal with JavaScript+CSS or use a library like JQuery.
(AJAX): Add event listeners to the checkboxes so that when a button is checked an asynchronous call is made back to a PHP script and the $_SESSION variable is updated accordingly. Again, this one depends on how comfortable you are with JavaScript.
Just keep in mind that PHP = ServerSide & JavaScript = ClientSide. While you can hack some PHP together to handle "clientside" stuff, its usually ugly and convoluted...
I did it without touching the database...
The checkbox fields are a php collection "cbgroup[]".
I then made a hidden text box with all the values which equal the primary keys of the selectable items mirroring the checkboxes. This way, I can iterate through the fake checkboxes on the current page and uncheck the checkboxes by ID that exist on the current page only. If the user does a search of items and the table changes, the selectable items remain! (until they destroy the session)
I POST the pagination instead of GET.
After the user selects their items, the page is POSTED and I read in the hidden text field for all the checkbox IDs that exist on that current page. Because PhP only tells you which ones are checked from the actual checkboxes, I clear only the ones from the session array that exist on the POSTED page from this text box value. So, if the user selected items ID 2, 4, 5 previously, but the current page has IDs 7,19, and 22, only 7, 19, and 22 are cleared from the SESSION array.
I then repopulate the array with any previously checked items 7, 19, or 22 (if checked) and append it to the SESSION array along with 2, 4, and 5 (if checked)
After they page through all the items and made their final selection, I then post their final selections to the database. This way, they can venture off to other pages, perhaps even adding an item to the dB, return to the item selection page and all their selections are still intact! Without writing to the database in some temp table every page iteration!
First, go through all the checkboxes and clear the array of these values
This will only clear the checkboxes from the current page, not any previously checked items from any other page.
if (array_key_exists('currentids', $_POST)) {
$currentids = $_POST['currentids'];
if (isset($_SESSION['materials']) ) {
if ($_SESSION['materials'] != "") {
$text = $_SESSION['materials'];
$delimiter=',';
$itemList = explode($delimiter, $text);
$removeItems = explode($delimiter, $currentids);
foreach ($removeItems as $key => $del_val) {
//echo "<br>del_val: ".$del_val." - key: ".$key."<br>";
// Rip through all possibilities of Item IDs from the current page
if(($key = array_search($del_val, $itemList)) !== false) {
unset($itemList[$key]);
//echo "<br>removed ".$del_val;
}
// If you know you only have one line to remove, you can decomment the next line, to stop looping
//break;
}
// Leaves the previous paged screen's selections intact
$newSessionItems = implode(",", $itemList);
$_SESSION['materials'] = $newSessionItems;
}
}
}
Now that we have the previous screens' checked values and have cleared the current checkboxes from the SESSION array, let's now write in what the user selected, because they could have UNselected something, or all.
Check which checkboxes were checked
if (array_key_exists('cbgroup', $_POST)) {
if(sizeof($_POST['cbgroup'])) {
$materials = $_POST['cbgroup'];
$N = count($materials);
for($i=0; $i < $N; $i++)
{
$sessionval = ",".$materials[$i];
$_SESSION['materials'] = $_SESSION['materials'].$sessionval;
}
} //end size of
} // key exists
Now we have all the items that could possibly be checked, but there may be duplicates because the user may have paged back and forth
This reads the entire collection of IDs and removes duplicates, if there are any.
if (isset($_SESSION['materials']) ) {
if ($_SESSION['materials'] != "") {
$text = $_SESSION['materials'];
$delimiter=',';
$itemList = explode($delimiter, $text);
$filtered = array();
foreach ($itemList as $key => $value){
if(in_array($value, $filtered)){
continue;
}
array_push($filtered, $value);
}
$uniqueitemschecked = count($filtered);
$_SESSION['materials'] = null;
for($i=0; $i < $uniqueitemschecked; $i++) {
$_SESSION['materials'] = $_SESSION['materials'].",".$filtered[$i];
}
}
}
$_SESSION['materials'] is a collection of all the checkboxes that the user selected (on every paged screen) and contains the primary_key values from the database table. Now all you need to do is rip through the SESSION collection and read\write to the materials table (or whatever) and select/update by primary_key
Typical form...
<form name="materials_form" method="post" action="thispage.php">
Need this somewhere: tracks the current page, and so when you post, it goes to the right page back or forth
<input id="_page" name="page" value="<?php echo $page ?> ">
if ($page < $counter - 1)
$pagination.= " next »";
else
$pagination.= "<span class=\"disabled\"> next »</span>";
$pagination.= "</div>\n";
Read from your database and populate your table
When you build the form, use something like this to apply the "checked" value of it equals one in the SESSION array
echo "<input type='checkbox' name='cbgroup[]' value='$row[0]'";
if (isset($filtered)) {
$uniqueitemschecked = count($filtered);
for($i=0; $i < $uniqueitemschecked; $i++) {
if ($row[0] == $filtered[$i]) {
echo " checked ";
}
}
}
While you're building the HTML table in the WHILE loop... use this. It will append all the select IDs to a comma separated text value after the loop
...
$allcheckboxids = "";
while ($row = $result->fetch_row()) {
$allcheckboxids = $allcheckboxids.$row[0].",";
...
}
After the loop, write out the hidden text field
echo "<input type='hidden' name='currentids' value='$allcheckboxids'>";

Categories