Looping through multi-dimensional array to pre-populate dynamically generated form - php

I am trying to create an ecommerce site. I have products that have different attributes (e.g. colour) and each of these needs to have their own model number and price etc,.
I have generated a form to gather this information and save it. However, I want to be able to save this info as a $_SESSION variable while users are adding products, so that they can come back to the price section and the form will be pre-populated with what they previously entered even though they haven't actually saved the product to the DB yet.
To do this I have a string that I treat as an array of items stored as a $_SESSION variable in PHP in the following format:
'item-test,100,20,20,20,20,£,1,item-test,100,20,20,20,20,£,2'
I parse this into an actual array I can deal with like so (when it gets to actually saving the product my SQL query is inside this foreach() loop):
if(isset($_SESSION['price_array'])){
$price_array = $_SESSION['price_array'];
$result = explode("item-",$price_array);
foreach($result as $item){
if(isset($item) && $item!=""){
$itemValue = explode(",",$item);
$product_model_no = $itemValue[0];
$product_value = $itemValue[1];
$product_discount = $itemValue[2];
$product_margin = $itemValue[3];
$product_shipping_domestic = $itemValue[4];
$product_shipping_other = $itemValue[5];
$product_currency = $itemValue[6];
$product_attribute = $itemValue[7];
}
}
}
So to generate this form I've another loop that goes through all of the possible attributes (not all products might come in all colours so only the ones stored in the $_SESSION apply). If I try to pre-populate this as it is my variables above only have the values for the last item in the array.
However if I nest this inside the other loop it will get the correct data but it will generate the form a number of times depending on how many items are in the array, with each iteration of the form having the values for that item in the array.
I know this is very convoluted to try explain and I can't really provide all my code because it is very complex and most of it is generated in PHP from other information in other locations.
Edit
The basics of how the form is being generated inside the other loop is as follows:
$params = [$attribute];
$sql = "SELECT * FROM attributes WHERE id=?";
$attributeResult = DB::run($sql,$params);
foreach ($attributeResult as $value) {
for ($i = 1; $i <= 15; $i++) {
//generate form here
if($i == $product_attribute){
// pre-populate form here
}
}
}

Related

PHP Query to UPDATE/DELETE a dynamically generated input field in a table

I have a Table where user can create row with adding input fields dynamically (combination with jquery). I'm successfully able to insert it into the mysql database.
If users want to edit the added already existing fields, I have an edit page where the values are fetched from the mysql DB and populated again into the dynamically creatable table.
Now there are the below probabilities:-
User only makes minor changes on the existing values. In that case
the table has to be UPDATED with the changed values
User Deletes one/multiple row(randomly selected and as per users wish). So when form submitted the php query should only DELETE that perticular row/s in the DB.
User ADDS another row to the previous existing row values, in that case the php query should UPDATE the previous values and INSERT the newly added row values.
The above sequence is not necessarilly restricted the same order. User can perform all the above three function simultaneously at the same time.
Now my problem is(only for the backend) I'm finding a hard time to frame a php & sql query so as to update to the mysql.
my php
if(isset($_POST['submit'])){
$number1 = count($_POST['item']); //
for($i=0; $i<$number1; $i++){
$item = strip_tags(trim($_POST['item'][$i]));
$description = strip_tags(trim($_POST['description'][$i]));
$unitcost = strip_tags(trim($_POST['unitcost'][$i]));
$qty = strip_tags(trim($_POST['qty'][$i])); // Quantity
$sno = strip_tags(trim($_POST['sno'][$i]));// serial number
//QUERY1 if minor updates to above variable then UPDATE (eg, qty value is changed from 3 to 4)
//QUERY2 if row is deleted then DELETE that particular row from db (eg, sno 3 deleted from the table should DELETE corresponding mysql DB values also)
//QUERY3 if row is added then that particular row values should be INSERT (eg, sno 4 is added which is not in the mysql db. So this has to be INSERTED.)
}
}
Pardon me to have asked such question. I'm wasting a whole lot of time with the above queries unable to execute properly. I only require an idea not necessarily the whole code.
Hope all of you out there would advice me some ideas on how this could be implemented. Thanks for the help in advance. Expecting a positive reply.
NB: Just to remind you again, The front end is a Dynamically ADD/DELETE Input Field table
This sounds like a frontend problem. You need to define how you tell the backend whats happening.
<input name="items[$i][name]" />
This will show up as nice array to loop through in php.
foreach($_POST[items] AS $item){
if( $item['delete'] ){
//delete code
}
}else{
//Insert/Update
}
If you want to delete something simply make the field hidden and add a flag to it.
<input type="hidden" name="items[$i][delete]" value="1" />
<input type="hidden" name="items[$i][id]" />
Thank for the reply, appreciate #ckrudelux and #codefather for their intention to help me.
Although their advise didn't help me to structure my query. So I had a long workaround and found out below solution. I'm posting the solution because I couldn't find any article online when it comes to UPDATE/DELETE a dynamically generated input table.
Hope this would be of help to someone.
So what I did basically is that I took all the values into array.
In my dynamically generated add input table code, I added an <input type="hidden" name="sno[]" value="newrow">. So this will be clubbed with the form post. I'm using the normal html post and not ajax.
now my submit.php has ben changed to below
if(isset($_POST['submit'])){
$productid = $_POST['productd'];// No striptag functions
// due to illustration purpose
// First of all, we need to fetch the querying db table.
// This is required in order to compare the existing row values
// with the posted values
$fetchproduct = $link->prepare("SELECT * FROM product WHERE productid=?");
$fetchproduct ->bind_param('s',$productid);
$fetchproduct ->execute();
$fetchresult = $fetchproduct ->get_result();
$serialnumber=array(); // Assigning array to fetch the primary key: Serial Number
while($row = $fetchresult->fetch_assoc()){
$serialnumber[] = $row["sno"];
}
//Newly Inserted Values
//$_POST['sno'] is taken from the dynamic input field defined earlier in this post.
//Basically what we are doing here is we are comparing (the values
//which have been posted from the primary page) and (values present in the db table).
//The difference will give an array of newly inserted table input field values
$insert = array_diff($_POST['sno'],$serialnumber);
//Deleted Values
// This will Difference those values in the db table and values which are
// deleted from the primary dynamic table page
$delete = array_diff($serialnumber,$_POST['sno']);
$countdelete = count($delete); // Counting how many values have been
// lined up for deleting
//Updated Values
// array_intersect will give us the common values present in both the array.
// This means that there is no deletion or insertion to the dynamic table fields.
$intersect = array_intersect($serialnumber, $_POST['sno']);
$update = array_values($intersect);
$countupdate = count($update);
//INSERT ADDED VALUES TO DB
foreach($insert as $key=>$ivalue){
// ID
if(isset($_POST['id'][$key]) && !empty($_POST['id'][$key])) {
$id = strip_tags(trim($_POST['id'][$key]));
}
// ITEM
if(isset($_POST['item'][$key]) && !empty($_POST['item'][$key])) {
$item = strip_tags(trim($_POST['item'][$key]));
}
// DESCRIPTION
if(isset($_POST['description'][$key]) && !empty($_POST['description'][$key])) {
$description = strip_tags(trim($_POST['description'][$key]));
}
// UNITCOST
if(isset($_POST['unitcost'][$key]) && !empty($_POST['unitcost'][$key])) {
$unitcost = strip_tags(trim($_POST['unitcost'][$key]));
}
// QUANTITY
if(isset($_POST['qty'][$key]) && !empty($_POST['qty'][$key])) {
$qty = strip_tags(trim($_POST['qty'][$key]));
}
// AMOUNT
if(isset($_POST['amount'][$key]) && !empty($_POST['amount'][$key])) {
$amount = strip_tags(trim($_POST['amount'][$key]));
}
// INSERT INTO THE DATABASE
$inserttable = $link->prepare("INSERT INTO product (productid, item, description, unitcost, qty, amount) VALUES(?,?,?,?,?,?)");
$inserttable->bind_param('ssssss', $id, $item, $description, $unitcost, $qty, $amount);
$inserttable->execute();
if($inserttable){
header( 'Location:to/your/redirect page.php' ) ; // NOT MANDADTORY, You can put whatever you want
$_SESSION['updatemsg'] = "Success";
}
}
//UPDATE EXISTING VALUES TO DB
for($j=0; $j<$countupdate; $j++){
// ID
if(isset($_POST['id'][$j]) && !empty($_POST['id'][$j])) {
$uid = strip_tags(trim($_POST['id'][$j]));
}
// ITEM
if(isset($_POST['item'][$j]) && !empty($_POST['item'][$j])) {
$uitem = strip_tags(trim($_POST['item'][$j]));
}
// DESCRIPTION
if(isset($_POST['description'][$j]) && !empty($_POST['description'][$j])) {
$udescription = strip_tags(trim($_POST['description'][$j]));
}
// UNITCOST
if(isset($_POST['unitcost'][$j]) && !empty($_POST['unitcost'][$j])) {
$uunitcost = strip_tags(trim($_POST['unitcost'][$j]));
}
// QUANTITY
if(isset($_POST['qty'][$j]) && !empty($_POST['qty'][$j])) {
$uqty = strip_tags(trim($_POST['qty'][$j]));
}
// AMOUNT
if(isset($_POST['amount'][$j]) && !empty($_POST['amount'][$j])) {
$uamount = strip_tags(trim($_POST['amount'][$j]));
}
// UPDATE THE DATABASE
$updatetable = $link->prepare("UPDATE product SET item=?, description=?, unitcost=?, qty=?, amount=? WHERE sno=?");
$updatetable->bind_param('ssssss', $uitem, $udescription, $uunitcost, $uqty, $uamount, $update[$j]);
$updatetable->execute();
if($updatetable){
$_SESSION['updatemsg'] = "Success";
}
}
//DELETE VALUES FROM DB
foreach($delete as $sno){
$deletetable = $link->prepare("DELETE FROM product WHERE sno=?");
$deletetable->bind_param('s', $sno);
$deletetable->execute();
if($deletetable){
$_SESSION['updatemsg'] = "Success";
}
}
}else {
$_SESSION['updatemsg'] = "Error";
}
}

insert array with dynamic amount of values to database

I am attempting to insert an array of image information into my database. The array consists of a ton of image information and originally i started with just allowing 3 images out of the array to be entered into the database.
The images detail goes into a table called print and each of the three image urls has a column of their own to go into, along with a caption for each image, the date the image was taken and its location. All of this info goes into one row with the users id.
// Assign images and data to appropriate variables
$image_one = $feed['0']['images']['standard_resolution']['url'];
$image_one_caption = htmlspecialchars($feed['0']['caption']['text'], ENT_QUOTES);
$image_one_date = $feed['0']['created_time'];
$image_one_location = $feed['0']['location']['name'];
$image_two = $feed['1']['images']['standard_resolution']['url'];
$image_two_caption = htmlspecialchars($feed['1']['caption']['text'], ENT_QUOTES);
$image_two_date = $feed['1']['created_time'];
$image_two_location = $feed['1']['location']['name'];
$image_three = $feed['2']['images']['standard_resolution']['url'];
$image_three_caption = htmlspecialchars($feed['2']['caption']['text'], ENT_QUOTES);
$image_three_date = $feed['2']['created_time'];
$image_three_location = $feed['2']['location']['name'];
However I now want to make it so that the number of prints entered into the table can vary from 3 up to 10 as a maximum. I'm wondering about the best way to do this.
I could simply assign the array values to more variables in the way shown above, however this is bulky and I feel unnecessarily repetitive.
I was thinking about a foreach loop, however I'm uncertain of how to insert each image and each images accompanying data into the correct columns of the users print row.
The other option would be to create a separate print_info table and store the users id and print_job number, then in the print table purely have the image info in separate rows with a print_job column to link the print_job to the users print_info row. is this the best way forward with this little problem?
What about this:
$numOfImages = 4; //the number you want
for ($i=0; $i < $numOfImages; $i++) {
$image = $feed[$i]['images']['standard_resolution']['url'];
$image_caption = htmlspecialchars($feed[$i]['caption']['text'], ENT_QUOTES);
$image_date = $feed[$i]['created_time'];
$image_location = $feed[$i]['location']['name'];
//...operation with $image
}

Passing multiple checkbox values to different columns of database

I am pretty new to PHP, but have tried searching for other questions similar to mine and been unable to find anything that is close enough to my situation to help me solve this.
I am trying to code a web page that allows users to select as many or as few items as they would like to order. The item values are identical to their Primary Key in the Item table.
Once submitted, each different item value should be input into the same row of a database table based on the date{pk}. Within that row, there are numerous columns: Item1ID, Item2ID, Item3ID, etc.
So far, the value of each item selected is assigned to a new array. However, I cannot simply input the array values into a column -- I need each array index to be placed into a sequential column. The code is below:
$date = new DateTime();
$td = $date->format('Y-m-d');
$x = 1;
$checkedItems = $_POST['Item'];
$count = count($checkedItems);
echo $count;
$foodID = "Item".$x."ID";
While($x<=$count){
if(isset($_POST['Item'])){
if (is_array($_POST['Item'])) {
foreach($_POST['Item'] as $values){
$selectedFoods = substr($values,0,4);
$addFoodOrderQuery= sprintf("UPDATE WeeklyBasketFoodOrder SET '%s' = %s WHERE `foodOrderDate` = '%s'",
$foodID, $selectedFoods, $td);
$result= mysqli_query($db, $addFoodOrderQuery);
}
}
} else {
$values = $_POST['Item'];
echo "You have not selected any items to order.";
}
$x++;
}
If you need any further clarification, please let me know. After submitting the code, the database item#ID tables are different, but they are now empty instead of "NULL."

Query 2 tables and combine data in a single array

I am trying to combine the results from 2 queries into a single array but am having problems getting the correct code.
I have a table called PrimaryEvents that I query to add to an array. This query works ok:
$rows = query("SELECT * FROM PrimaryEvents WHERE unit = ? ORDER BY event", $unit);
I add the data to an array using the following:
foreach ($rows as $row)
{
// $event = lookup($row["event"]); (removed as spotted by sergio not required)
$event["event"] = $row["event"];
$event["validity"] = $row["validity"];
$event["eventsrequired"] = $row["eventsrequired"];
$event["unit"] = $row["unit"];
$event["role"] = $row["role"];
//now we have the data lets try and do something to it
if ($event["role"] == "0")
{
//then the user is active so change value to a YES
$event["role"] = "ALL";
}
//add our stock to the portfolio array
$portfolio[] = $event;
}
So far everything works well. I would like to query a separate table and add certain results to the array portfolio[];
$rowsCompleted = query("SELECT * FROM portfolio WHERE id = ? ORDER BY name", $_SESSION["id"]);
My original plan was to use the following additional code to add the data of interest to the portfolio[] but it doesn't work:
//now add individual stats to the array
foreach($rowsCompleted as $row)
{
if ($portfolio["event"] == $row["name"]
{
//then add our number and date to the array
$portfolio["datecompleted"] = $row["datecompleted"];
$portfolio["number"] = $row["number"];
}
//else do nothing
}
My final aim was to pull the datacompleted value and number value from the portfolio table and then add it to the array ONLY if the event name matches the name in portfolio array.
Hopefully I have described my problem and required behaviour well enough.
Thanks for nay help that can be offered, I am new to php/sql so learning as I go.
Andy
EDIT:
Also tried the following loop to try and loop through the array:
//now add individual stats to the array
foreach($rowsCompleted as $row)
{
foreach ($portfolio["event"] as $item)
{
if ($portfolio["event"] == $row["name"]
{
//then add our number and date to the array
$portfolio["datecompleted"] = $row["datecompleted"];
$portfolio["number"] = $row["number"];
}
}
//else do nothing
}
EDIT2: To try and make my question more clear: The Primary-events table lists all the events a specific user has to complete. The portfolio table tracks which events have been completed by the user (by means of date-completed and number).
I want to run a query that lists all the events from Primary-events, then into those results add the date-completed and number from the users portfolio. If the answer is blank from the portfolio then the user has not yet completed the event but I would still like to list it from the Primary-events table data.
I tried 2 queries to start with as it seemed to follow what I was trying to achieve.
EDIT3:
New code with help from Barmar
foreach ($rows as $row) {
$event = lookup($row["event"]);
$event["event"] = $row["event"];
$event["validity"] = $row["validity"];
// $event["datecompleted"] = $row["datecompleted"];
// $event["number"] = $row["number"];
$event["eventsrequired"] = $row["eventsrequired"];
$event["unit"] = $row["unit"];
$event["role"] = $row["role"];
//now we have the data lets try and do something to it
if ($event["role"] == "0") {
//then the user is active so change value to a YES
$event["role"] = "ALL";
}
//add our stock to the portfolio array
$portfolio[] = $event;
//now add individual stats to the array
foreach ($rowsCompleted as $row) {
foreach ($portfolio as &$item) {
if ($item["event"] == $row["name"]) {
//then add our number and date to the array
$item["datecompleted"] = $row["datecompleted"];
$item["number"] = $row["number"];
}
}
}
}
The page still isn't being displayed by chrome so guessing i've missed something.
EDIT4: Page displayed, I am now getting undefined index errors when the table is rendered on the html page.
Specifically the undefined index errors are for date-completed and number. I am taking it to mean that these values are not being added to the portfolio array? Do try and help I have added an Else statement (as below) to ensure that even if the event isn't available the index is:
//now add individual stats to the array
foreach($rowsCompleted as $row)
{
foreach ($portfolio as &$item)
{
if ($item["event"] == $row["name"])
{
//then add our number and date to the array
$item["datecompleted"] = $row["datecompleted"];
$item["number"] = $row["number"];
}
else
{
$item["datecompleted"] = "Never";
$item["number"] = "0";
}
}
}
EDIT 5: Near Success. Sorry to reopen this but I have just noticed behaviour I wasn't expecting: The nested loop only sets the date-completed and number for the first value to matches from the portfolio table. The follow on values are not set. It would seem like the nested loop isn't stepping through all of the portfolio values, and just exiting once the first "event" == "name".
EDIT 6: Sample data and clarification on desired functions:
portfolio sample data
|id|name |number|datacompleted
|21|event1 |3 |2014-07-07
|15|event1 |5 |2014-07-05
|21|event2 |5 |2014-05-08
|15|event1 |1 |2013-05-05
id is the id of the user that completed the event
number is the number of events completed
PrimaryEvents sample data
|id|event |validity|eventsrequired
|1 |event1 |7 |10
|1 |event2 |25 |1
|1 |event3 |12 |50
id is the id of the user that created the entry (used for historic purpose only)
The desired functionality is:
The query should create a an array to allow a html table to be created of everything within the Primary-events table. This table lists the events the user must complete.
The second query or current nested loop should gather the data from the portfolio table for the current user id, then match the event name to the name in the Primary-events array and update (if present) the number and date-completed value. (I.E populate the data for the events that the user has completed).
The current code merges the data from portfolio only for the first match, but then the nested loop seems to exit.
Hopefully this is a more clear description of what I am trying to achieve.
EDIT: I have changed the functionality to use the Left join statement below but am still having problems:
The table only contains some of the events from primary-events table and not all of them. The events being pulled over are only those that the user has completed, the ones the user has not yet completed are not being shown.
EDIT: This query seems to work:
$allEvents = query("SELECT * FROM PrimaryEvents LEFT JOIN portfolio ON (PrimaryEvents.event = portfolio.name) WHERE PrimaryEvents.event = ? AND (portfolio.id = ? Or portfolio.id is null) ORDER BY PrimaryEvents.event", $currentEvent, $_SESSION["id"]);
You need to notice that portfolio is not associative array but multidimensional array, so you cannot access it using $portfolio["event"]. You should use $portfolio[0]["event"], $portfolio[1]["event"] and so on.
It's hard to show you exact solution because I don't know how those arrays/database queries should be merged.
EDIT
It seems your query should look like this:
query("SELECT * FROM PrimaryEvents e LEFT JOIN portfolio p ON e.event = p.name WHERE e.unit = ? AND p.id = ? ORDER BY e.event", $unit,$_SESSION["id"]);
EDIT2
I haven't proposed nested loop (as it's now in modified question) because of performance loss.
You're getting closer with your second query, but still confused about what's in each array.
foreach($rowsCompleted as $row)
{
foreach ($portfolio as &$item) // Need to use reference so we can update it
{
if ($item["event"] == $row["name"])
{
//then add our number and date to the array
$item["datecompleted"] = $row["datecompleted"];
$item["number"] = $row["number"];
break;
}
}
}
To avoid the nested loop, it would be better for $portfolio to be an associative array. Change the code for your initial query to use:
//add our stock to the portfolio array
$portfolio[$event["name"]] = $event;
Then the second loop becomes:
foreach($rowsCompleted as $row)
{
$name = $row["name"];
if (isset($portfolio[$name]) {
$portfolio[$name]["datecompleted"] = $row["datecompleted"];
$portfolio[$name]["number"] = $row["number"];
}
}

Getting value from multiple drop down menus in PHP

Ive been battling away with the following problem
Ive got a page where I pull names from players specific to their positions in a sport squad.
Example: I will display all the Wings in the squad using a dropdown where a coach can then pick his wing for the game.
There are dropdowns for each different position
The aim of the page is to let the coach quickly select his team for a fixture
After the coach selected his team he will, select the opponents for which the selected team will play against.
When he clicks submit the selected oppents and players will get stored in two arrays which will get called to display the team selected and their opponents on a new page. (After which it will get uploaded to the DB.)
I am having trouble getting the values from the select list to display on the new page.
I guess I have to do something like this on the new page:
foreach ($_REQUEST['opponents'] as $opponents){
print $opponents;
echo'<br>';
}
but it is not giving the desired results.
Strangely what gets printed is the variable name from the previous page select menu.
Upon further inspection I did a vardump on the new page and it says that $opponenets gets passed a value of string which is the variable name and not the value thereof?
My page looks like this
My question is how would I go abouts getting the values from the select dropdowns
if(isset($_POST["submit"]))
{
foreach ($_REQUEST['opponents'] as $against){
var_dump($against);
print $against;
echo'<br>';
}
}
else
{
echo'<h1>Select your Team</h1>';
$x = array("THP", "HKR", "LHP", "LH", "FLH"); //players positions gets assigned to x which will be used to query the database
echo '<form name="playerselect" method="post" action="">';
//query database with different query after each loop
for ($i = 0; sizeof($x) > $i; $i++)
{
//query where position field equeals variable x
$result = mysql_query("SELECT `name`, `position` FROM `player_info`
WHERE `position` = '$x[$i]'") or die(mysql_error()) ;
//Gets data from DB and assigns values to arrays below
while($row = mysql_fetch_array($result))
{
$playername[] = $row['name'];
$position[] = $row['position'];
}
//print player position
print $position[0];
echo'<br>';
//unset the array so that it is empty for the next query in the new loop
unset($position);
echo '<select name="players[]" >' ;
foreach ($playername as $name )
{
//Put playernames relevant to the position in the option element
echo'<option value="$name" selected="selected">'.$name;'</option>';
echo'<br>';
}
echo'</select>';
//unset array so that its contents is empty for the next query in the new loop
unset($playername);
echo'<br>';
}
You cannot. Your submit will only transmit select values. This is not a bug, it is a feature. You do not want to send data back and forth from/to the server/client which is known to both of them.
On the server you are free to query your database at any time. You can also cache your select list into the $_SESSION variable in your initial list read. However this is advanced fittling as your cache list may become outdated and also your server memory utilization must leave space for file caching (the SESSION cache goes to files).
If you go for the database query you may need some ID as sort of anchor. Just put the into the $_SESSION variable - eg.:
$_SESSION['positions']=$x;
In your example the $x seems to be static, which obviously reduces the need to cache it into the $_SESSION - however on other occasions you may need this method.

Categories