foreach loop in php needs debugging - php

While I had no success with php routing since is above my current knowledge I tried the implementation below:
$query = "SELECT * FROM persons WHERE SURNAME LIKE 'Ω%' ORDER BY SURNAME ASC;";
$result = mysqli_query($con, $query); //the selected query has 2 results!
/* determine number of rows result set */
$row_cnt = mysqli_num_rows($result);
printf("results (%d).", $row_cnt);
// Check result
// This shows the actual query sent to MySQL, and the error. Useful for debugging.
if (!$result) {
$message = 'Invalid query: ' . mysqli_error($con) . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
function generateTableFromResult($result) {
$x = 1;
$html = "<table>";
while($row = mysqli_fetch_array($result)) {
foreach($row as $column => $value) {
copy("persons.php","newfile".$x.".php");
$html.="<tr><th>".$column."</th><td>".$value."</td></tr>";
$myfile = fopen("newfile".$x.".php", "w") or die("Unable to open file!");
fwrite($myfile, $html);
}
$x++;
}
$html .= "</table>";
return $html;
}
// usage:
// ...
$result = mysqli_query($con, $query);
echo generateTableFromResult($result);`
The above script creates:
newfile1.php --> table + table (first + second result)
newfile2.php --> table + table (first + second result)
while I want:
newfile1.php --> table (first result)
newfile2.php --> table (second result)
What am I missing here?
edit:
example content of newfile1.php:
CODE_NO 12101
SURNAME ΩΝΑΣΗ
FIRST_NAME ΧΡΙΣΤΙΝΑ
SOURCE1 ΗΛΙΟΥ
SOURCE2
SOURCE3
PROV ΟΙΚΟΓΕΝΕΙΑΚΗ ΣΧΕΣΗ ΚΑΘΕΤΗ ΜΕ ΚΙΝΗΤΙΚΟΤΗΤΑ
SEX ΓΥΝΑΙΚΑ
BIRTH 1950
DEATH 1989
PLACE ΜΕΓΑΛΟ ΑΣΤΙΚΟ ΚΕΝΤΡΟ
REGION ΑΛΛΕΣ ΞΕΝΕΣ ΧΩΡΕΣ
EDUCATION ΜΕΤΑΠΤΥΧΙΑΚΕΣ ΣΠΟΥΔΕΣ
SPECIAL
WRITING
POLITICAL
MANAGERIAL
MILITARY
RELIGIOUS
SPIRITUAL
SCIENTIFIC
NOBLE ΝΑΙ
CULTURAL
FINANCIAL ΝΑΙ
CONSTITUTIONAL
OPPOSITION
PROF1 Επιχειρηματίας
PROF2 Νεώτερη αριστοκρατική ελίτ πλουτου
PROF3
PROF4
PROF5
PARTY
ACTIVITY1
ACTIVITY2
1800_1832
1833_1862
1863_1911
1912_1922
1923_1944
1945_1973 ΝΑΙ
1974_ ΝΑΙ
HIERARCHY Ανωτάτη Ελίτ
LEADERSHIP
HERE starts table 2 This is what tables look like. Remember I want each table to be written per person/file.
CODE_NO 12100
SURNAME ΩΝΑΣΗΣ
FIRST_NAME ΑΡΙΣΤΟΤΕΛΗΣ
SOURCE1 ΗΛΙΟΥ
SOURCE2 ΔΡΑΝΔΑΚΗ
SOURCE3 ΕΚΔΟΤΙΚΗ
PROV ΑΓΝΩΣΤΗ
SEX ΑΝΔΡΑΣ
BIRTH 1906
DEATH 1975
PLACE ΑΓΡΟΤΙΚΕΣ- ΝΗΣΙΩΤΙΚΕΣ
REGION ΜΙΚΡΑ ΑΣΙΑ
EDUCATION ΔΕΝ ΔΗΛΩΝΕΙ
SPECIAL
WRITING
POLITICAL
MANAGERIAL
MILITARY
RELIGIOUS
SPIRITUAL
SCIENTIFIC
NOBLE ΝΑΙ
CULTURAL
FINANCIAL ΝΑΙ
CONSTITUTIONAL
OPPOSITION
PROF1 Εφοπλιστής
PROF2 Νεώτερη αριστοκρατική ελίτ πλουτου
PROF3
PROF4
PROF5
PARTY
ACTIVITY1
ACTIVITY2
1800_1832
1833_1862
1863_1911
1912_1922
1923_1944 ΝΑΙ
1945_1973 ΝΑΙ
1974_
HIERARCHY Yψιστη Μορφή Ελίτ
LEADERSHIP

This should produce the output you want (from your comments):
function generateTableFromResult($result) {
$x = 1;
$html = '';
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
// Add the open-table tag
$html = '<table>';
// Iterate through the columns and add them to our variable
foreach($row as $column => $value) {
$html .= "<tr><th>".$column."</th><td>".$value."</td></tr>";
}
// Add the close-table tag
$html .= "</table>";
// Now, since we've added all the rows for that person,
// create, populate and store the file
file_put_contents("newfile".$x.".php", $html);
// Increment $x before we jump to the next person
$x++;
}
// However, this will only return the table for the last person
return $html;
}
I also changed your fopen and copy (which didn't really make sense) to one simple command: file_put_contents()
A big shout out to #ishegg that helped narrow down the issue

By default, the fetch mode for mysqli_fetch_array() is MYSQLI_BOTH, which means it's getting each result in associative and numeric form. That, in addition to your double-looping over the results, gives you the results you're getting.
To fix it, you can use MYSQLI_ASSOC (or use mysqli_fetch_assoc()), so it only gets each row once.
function generateTableFromResult($result) {
$x = 1;
$html = "<table>";
while($row = mysqli_fetch_assoc($result)) {
foreach($row as $column => $value) {
copy("persons.php","newfile".$x.".php");
$html.="<tr><th>".$column."</th><td>".$value."</td></tr>";
$myfile = fopen("newfile".$x.".php", "w") or die("Unable to open file!");
fwrite($myfile, $html);
}
$x++;
}
$html.="</table>";
return $html;
}
Or, keeping your original function:
function generateTableFromResult($result) {
$x = 1;
$html = "<table>";
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
foreach($row as $column => $value) {
copy("persons.php","newfile".$x.".php");
$html.="<tr><th>".$column."</th><td>".$value."</td></tr>";
$myfile = fopen("newfile".$x.".php", "w") or die("Unable to open file!");
fwrite($myfile, $html);
}
$x++;
}
$html.="</table>";
return $html;
}
Also, as #MagnusEriksson points out, you're appending the content to $html each time, so you will still get both results in the second file. To avoid this, put $html = "table"; inside the foreach loop:
function generateTableFromResult($result) {
$x = 1;
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
foreach($row as $column => $value) {
copy("persons.php","newfile".$x.".php");
$html = "<table>";
$html.="<tr><th>".$column."</th><td>".$value."</td></tr>";
$html.="</table>";
$myfile = fopen("newfile".$x.".php", "w") or die("Unable to open file!");
fwrite($myfile, $html);
}
$x++;
}
return $html;
}

Related

unable to generate multiple random words at a time using order by rand using php mysql

Hi friends am trying to produce random words using order by rand but unable to produce.Here is my code
for($i=0;$i< 10;$i++) {
$result = mysqli_query($conn,"SELECT * FROM questions ORDER BY RAND() LIMIT 2");
if (!$result) {
/*die('Invalid query: ' . mysql_error());*/
die("Query failed".mysqli_error());
}
while ($row = mysqli_fetch_array($result)) {
$meta_descriptions = '{' $row['fact'] . ' ' . '|' $row['fact'] . '|' . $row['fact']}';
echo $meta_descriptions;
}
}
My questions table has one column that is column fact. i t has three values like
apple
ball
cat
Am getting output as
ball |ball| ball only
I want it to be random like
ball|cat|apple
How can I generate it
See this statement inside your while() loop,
$meta_descriptions = '{' $row['fact'] . ' ' . $row['fact'] . '}';
You're using same column value two times in each iteration of while() loop. Simply change your while() code section in the following way,
$meta_descriptions = '';
while ($row = mysqli_fetch_array($result)) {
$meta_descriptions .= $row['fact'] . '|';
}
$meta_descriptions = rtrim($meta_descriptions, '|');
echo $meta_descriptions;
Alternative method:
Create an empty array in the beginning. In each iteration of while() loop, push $row['fact'] value to this array. And finally apply implode() function on this array to get the desired result.
So your code should be like this:
$meta_descriptions = array();
while ($row = mysqli_fetch_array($result)) {
$meta_descriptions[] = $row['fact'];
}
$meta_descriptions = implode('|', $meta_descriptions);
echo $meta_descriptions;
change inside your while loop.
$meta_descriptions = '{';
$descriptions = array();
while ($row = mysqli_fetch_array($result)) {
$descriptions[] = $row['fact'];
}
$meta_descriptions .= implode(" | ",descriptions);
$meta_descriptions .= '}';
echo $meta_descriptions;

PHP converting JSON file into excel table is formatted incorrectly

I have made a PHP file that takes this JSON-based file: http://www.yellowpages.com.iq/ajax/get/register/Categories.php
and converts it into an excel-formatted-table with the formatting of (.cvs) using this code :
$contents = file_get_contents('http://www.yellowpages.com.iq/ajax/get/register/Categories.php');
$data = JSON_decode($contents);
$excel_file = fopen("file.csv", "a+");
$table = "<table border='1'>";
foreach($data as $elem) {
$table .= "<tr>";
foreach($elem as $key => $prop) {
$table .= "<th>$key</th>";
$table .= "<td>$prop</td>";
fwrite($excel_file, "$key,$prop\n");
}
$table .= "</tr>";
}
$table .= "</table>";
echo $table;
But the problem being, is it takes the data and displays it correctly, although it tends to format it like so: id 1
category Advertising
id 2
category Agriculture & FoodÂ
id 3
category Air condition
id 4
category Airlines
id 5
Aluminium & Glass
Instead of what I'm trying to make it look like which I made manually:
Any help would be appreciated!
You could change the code using fputcsv, which takes care of double quotes and escaping them.
For that you need to get the JSON as an associative array (provide the second argument true):
$data = JSON_decode($contents, true);
And then the loop you have would be replaced with this:
// "loop" for the header (only 1 iteration)
foreach($data as $elem) {
$table .= "<tr><th>" . implode("</th><th>", array_keys($elem)) . "</th></tr>";
fputcsv($excel_file, array_keys($elem));
break; // only need one row for header
}
// Restart loop for the data
foreach($data as $elem) {
$table .= "<tr><td>" . implode("</td><td>", $elem) . "</td></tr>";
fputcsv($excel_file, $elem);
}

Generating XML from SQL using Mysqli

I'm trying to pull all the data from my users table and display it in XML format. The connection works fine and everything as I have a login and registration set up fine, but I can't seem to get this to display anything other than a white screen.
I've found lots of different tutorials on how to do it with mysql but not mysqli. what am i missing?
generatexml.php
<?php
include 'connection.php';
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
$root_element = $config['users'];
$xml .= "<$root_element>";
if ($result = $mysqli->query("SELECT * FROM users", MYSQLI_USE_RESULT)) {
while($row = $result->fetch_assoc())
{
$xml .= "<".$config['users'].">";
//loop through each key,value pair in row
foreach($result_array as $key => $value)
{
//$key holds the table column name
$xml .= "<$key>";
//embed the SQL data in a CDATA element to avoid XML entity issues
$xml .= "<![CDATA[$value]]>";
//and close the element
$xml .= "</$key>";
}
$xml.="</".$config['users'].">";
echo $xml;
}
}
?>
I struggle a lot to find out this solution in mysqli format but nowhere i found the solution. Below is the solution i figured. Run this demo and map it your requirement, surely it will help.
<?php
//Create file name to save
$filename = "export_xml_".date("Y-m-d_H-i",time()).".xml";
$mysql = new Mysqli('server', 'user', 'pass', 'database');
if ($mysql->connect_errno) {
throw new Exception(sprintf("Mysqli: (%d): %s", $mysql->connect_errno, $mysql->connect_error));
}
//Extract data to export to XML
$sqlQuery = 'SELECT * FROM t1';
if (!$result = $mysql->query($sqlQuery)) {
throw new Exception(sprintf('Mysqli: (%d): %s', $mysql->errno, $mysql->error));
}
//Create new document
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
//add table in document
$table = $dom->appendChild($dom->createElement('table'));
//add row in document
foreach($result as $row) {
$data = $dom->createElement('row');
$table->appendChild($data);
//add column in document
foreach($row as $name => $value) {
$col = $dom->createElement('column', $value);
$data->appendChild($col);
$colattribute = $dom->createAttribute('name');
// Value for the created attribute
$colattribute->value = $name;
$col->appendChild($colattribute);
}
}
/*
** insert more nodes
*/
$dom->formatOutput = true; // set the formatOutput attribute of domDocument to true
// save XML as string or file
$test1 = $dom->saveXML(); // put string in test1
$dom->save($filename); // save as file
$dom->save('xml/'.$filename);
?>
If you have access to the mysql CLI, here's my quick hack for achieving this:
$sql = "SELECT * FROM dockcomm WHERE listname = 'roortoor'
and status IN ('P','E') and comm_type IN ('W','O')
and comm_period NOT IN ('1','2','3','4') order by comment_num";
$cmd = "/usr/bin/mysql -u<person> -h<host> -p<password> <database> --xml -e \"$sql\";";
$res = system($cmd ,$resval);
echo $res;
Here is a solution using php only. You where close to getting it right. This was the key part of the code that I changed "$row as $key => $data" used $row instead of $result_array, ie. iterate through row not the result_array (this contains the entire dataset). Hope this helps someone.
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$value .="<record>\r\n";
//loop through each key,value pair in row
foreach($row as $key => $data)
{
//$key holds the table column name
$vals = "\t" . "<". $key . ">" . "<![CDATA[" . $data . "]]>" . "</" . $key . ">" . "\r\n";
$value = $value . $vals;
//echo $value;
}
$value .="</record>\r\n";
$count++;
}
} else {
// echo "0 results";
}
$conn->close();
One possible issue could be this line:
if ($result = $mysqli->query("SELECT * FROM users", MYSQLI_USE_RESULT)) {
Try the procedural approach instead of the object oriented approach. I do not know if $mysqli is defined in connection.php, but it is possible that you mixed it up.
if ($result = mysqli_query('SELECT * FROM users', MYSQLI_USE_RESULT)) {
This could resolve the white screen error.
I noticed two other things:
(1) One tiny effectiveness issue:
$xml = '<?xml version="1.0" encoding="UTF-8"?>';
So you do not need to escape every single quotation mark.
(2) One serious XML issue: The root element needs to be closed before you echo your $xml.
$xml .= "</$root_element>";
echo $xml;
Generally, for your purpose, it would be safer to use PHP's XMLWriter extension, as already proposed.

Insert XML to MySQL db whilst making sure it is UTF8 and just in plain text (no symbols - é and such)

I'm learning PHP or trying to by messing around with this small project.
I receive an XML weekly that I need to put into a mysql db, here's a small sample of what it looks like (It's usually a 35 children per Offer 50,000 Offer file.)
<?xml version="1.0" encoding="iso-8859-1"?>
<Offers>
<Offer>
<ProductName>10073482</ProductName>
<Manufacturer>Random Brand</Manufacturer>
<Description>Loerm ipsum....100-3000characters</Description>
<ModelNumber>5191181</ModelNumber>
<Price>29.99</Price>
</Offer>
<Offer>
<ProductName>10073482</ProductName>
<Manufacturer>Random Brand</Manufacturer>
<Description>Loerm ipsum....100-3000characters</Description>
<ModelNumber>5191181</ModelNumber>
<Size>Large</Size>
<Price>29.99</Price>
</Offer>
</Offers>
I guess ideally I want to:
import the XML make sure its all websafe
make it UTF-8
strip all symbols such as é
find all the used fields per product
make a table with that info
force that massive XML into the table
After import I should have 48,000 items yet playing with different encode's like urlencode sometimes I get 26,000 and another time 52,000.
Here's what I've got so far: (Be gentle)
<?php
ini_set('display_errors','On');
ini_set('max_execution_time', 300);
// Establish connection to database
$con2 = mysql_connect("localhost","root","root");
if (!$con2) {
die('Could not connect: ' . mysql_error());
}
$selectdb = mysql_select_db("f1", $con2);
if (!$selectdb) {
die('Database not used: ; ' . mysql_error());
}
// Vars
$name = $_GET['name'];
$filename = $name . ".xml";
$tableCreateQuery = "CREATE TABLE $name ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,";
// Load XML
if (file_exists($filename)) {
$xml = simplexml_load_file($filename);
foreach ($xml->children()->children() as $child){
$currentAttrib = $child->getName();
// Create query to create mysql table
$tableCreateQuery .= " `$currentAttrib` TEXT,";
}
$tableCreateQuery = rtrim($tableCreateQuery, ",");
$tableCreateQuery .= ") CHARACTER SET utf8";
// Create mysql table
mysql_query($tableCreateQuery);
// Loop through adding XML to new mysql table
$pCount = 0;
foreach ($xml->children() as $child){
$pCount++;
$theColumnsArr = array();
$theColumnsStr = "";
$theDataArr = array();
$theDataStr = "";
$i = 0;
foreach ($child->children() as $attrib){
$attrName = $attrib->getName();
$theColumnsArr[$i] = $attrName;
$theDataArr[$i] = urlencode(utf8_encode($attrib));
$i++;
}
$k = 0;
foreach ($theColumnsArr as $value) {
$colname = $theColumnsArr[$k];
$coldata = $theDataArr[$k];
$theColumnsStr .= "`$colname`,";
$theDataStr .= "'$coldata',";
$k++;
}
$theColumnsStr = rtrim($theColumnsStr, ",");
$theDataStr = rtrim($theDataStr, ",");
$theRow = "INSERT INTO $name ($theColumnsStr) VALUES ($theDataStr)";
mysql_query($theRow) or die(mysql_error());
}
echo $pCount . " products added to database";
} else {
exit("Failed to open $filename");
}
mysql_close($con2);
?>

Creating a page that detects multiple usernames when they login.PHP

I want to increment $userCount by 1 every time $data and $fileLineArr2[0] have the same value. Could someone explain why $userCount remains 0? I'm a programming student, so please keep help in a way that is understandable to someone with only intermediate experience.
if(!empty($_GET["user"]) && !empty($_GET["pass"]) && !empty($_GET["fname"]) && !empty($_GET["lname"])){
$handle = fopen($accountInfo, 'a') or die('Cannot open file: '.$accountInfo);
$data = $_GET["user"]."; ";
$data = strtoupper($data);
fwrite($handle, $data);
$data2 = $_GET["pass"]."; ";
fwrite($handle, $data2);
$data3 = $_GET["fname"]."; ";
fwrite($handle, $data3);
$data4 = $_GET["lname"].";\n";
fwrite($handle, $data4);
fclose($handle);
$reading2 = fopen($accountInfo, 'r') or die('Cannot open file: '.$accountInfo);
echo "$userCount";
while(!feof($reading2)){
$fileLines2 = fgets($reading2);
$fileLineArr2 = (explode("; ", $fileLines2));
//print_r($fileLineArr2);
**if($fileLineArr2[0] == $data)
{
$userCount++;
}**
echo "$fileLineArr2[0] ";
echo " $data". "\n";
echo "$userCount";
}
fclose($reading2);
if($userCount > 1)
{
$validSignUp = false;
?>
<font color='red'>Username already taken!</font>
<?php
}
elseif($userCount == 0)
{
;
}
else
{
$validLogin = true;
$validSignUp = true;
}
}
When reading from a file, there is an invisible new line character at the end of the string. You will want to remove that and then compare against the $data.
To remove the new line character, you can do something like
$string = trim(preg_replace('/\s+/', ' ', $string));
Where $string is the line from the file.
EDIT
Based on a discussion in the comments section, this is not what you want.
What you will want to do is the following:
$line = explode('; ', $lineData);
Where $lineData is the information being read from the file.
This will give you an array of all the elements that were listed on the line. We know that the username is listed in the first position, IE $line[0]. So we compare our data with that.
if ($line[0] == $data) {
$userCount++;
}
Where $data is the information we are comparing against.

Categories