double output from mysql in php - php

I am selecting the tables names from an opencart install.
trying to output the result(single column) as a string formated like a JSON array.
here is the code:
<?php
function getTableNames()
{
//Change these variables depending on the server it will be used on
$server = 'localhost';
$user = 'User1';
$pass = 'pass';
$DBName = 'OpenCartTest';
//returns a single column of all tables in a mysql database named "OpenCartTest"
$tablesGetSQL = 'Select `table_name` from `information_schema`.`TABLES` where `table_schema` like "OpenCartTest" AND `table_name LIKE "oc_customer%"';
$conn = new mysqli($server, $user, $pass, $DBName);
$JSONStringArray = '[';
if(mysqli_connect_errno())
{
echo '---unauthorized---';
}
else
{
$result = $conn->query($tablesGetSQL);
$l = $result->num_rows;
if($l > 0)
{
//for($i = 0;$i < $l;$i++)
while($row = $result->fetch_assoc())
{
//$row = $result->fetch_assoc();
foreach($row as $item)
{
//echo $item . "|";
$JSONStringArray .= "'" . $item . "',";
}
}
}
$JSONStringArray .= substr($JSONStringArray, 0, -1) . ']';
$conn->close();
return $JSONStringArray;
}
}
$output = getTableNames();
echo substr_count($output, "[") . '<br>';
echo $output;
?>
The output is doubled for some reason, there are 2 '[', yet I only set it once to the string. There is also no closing ']' on the first line.
output:
2
['oc_address','oc_affiliate','oc_affiliate_activity','oc_affiliate_login','oc_affiliate_transaction','oc_api','oc_attribute','oc_attribute_description','oc_attribute_group','oc_attribute_group_description','oc_banner','oc_banner_image','oc_banner_image_description','oc_category','oc_category_description','oc_category_filter','oc_category_path','oc_category_to_layout','oc_category_to_store','oc_country','oc_coupon','oc_coupon_category','oc_coupon_history','oc_coupon_product','oc_currency','oc_custom_field','oc_custom_field_customer_group','oc_custom_field_description','oc_custom_field_value','oc_custom_field_value_description','oc_customer','oc_customer_activity','oc_customer_ban_ip','oc_customer_group','oc_customer_group_description','oc_customer_history','oc_customer_ip','oc_customer_login','oc_customer_online','oc_customer_reward','oc_customer_transaction','oc_download','oc_download_description','oc_event','oc_extension','oc_filter','oc_filter_description','oc_filter_group','oc_filter_group_description','oc_geo_zone','oc_information','oc_information_description','oc_information_to_layout','oc_information_to_store','oc_language','oc_layout','oc_layout_module','oc_layout_route','oc_length_class','oc_length_class_description','oc_location','oc_manufacturer','oc_manufacturer_to_store','oc_marketing','oc_modification','oc_module','oc_option','oc_option_description','oc_option_value','oc_option_value_description','oc_order','oc_order_custom_field','oc_order_fraud','oc_order_history','oc_order_option','oc_order_product','oc_order_recurring','oc_order_recurring_transaction','oc_order_status','oc_order_total','oc_order_voucher','oc_osapi_last_modified','oc_product','oc_product_attribute','oc_product_description','oc_product_discount','oc_product_filter','oc_product_image','oc_product_option','oc_product_option_value','oc_product_recurring','oc_product_related','oc_product_reward','oc_product_special','oc_product_to_category','oc_product_to_download','oc_product_to_layout','oc_product_to_store','oc_recurring','oc_recurring_description','oc_return','oc_return_action','oc_return_history','oc_return_reason','oc_return_status','oc_review','oc_setting','oc_stock_status','oc_store','oc_tax_class','oc_tax_rate','oc_tax_rate_to_customer_group','oc_tax_rule','oc_tg_tglite_revolution_slider','oc_upload','oc_url_alias','oc_user','oc_user_group','oc_voucher','oc_voucher_history','oc_voucher_theme','oc_voucher_theme_description','oc_weight_class','oc_weight_class_description','oc_zone','oc_zone_to_geo_zone',
['oc_address','oc_affiliate','oc_affiliate_activity','oc_affiliate_login','oc_affiliate_transaction','oc_api','oc_attribute','oc_attribute_description','oc_attribute_group','oc_attribute_group_description','oc_banner','oc_banner_image','oc_banner_image_description','oc_category','oc_category_description','oc_category_filter','oc_category_path','oc_category_to_layout','oc_category_to_store','oc_country','oc_coupon','oc_coupon_category','oc_coupon_history','oc_coupon_product','oc_currency','oc_custom_field','oc_custom_field_customer_group','oc_custom_field_description','oc_custom_field_value','oc_custom_field_value_description','oc_customer','oc_customer_activity','oc_customer_ban_ip','oc_customer_group','oc_customer_group_description','oc_customer_history','oc_customer_ip','oc_customer_login','oc_customer_online','oc_customer_reward','oc_customer_transaction','oc_download','oc_download_description','oc_event','oc_extension','oc_filter','oc_filter_description','oc_filter_group','oc_filter_group_description','oc_geo_zone','oc_information','oc_information_description','oc_information_to_layout','oc_information_to_store','oc_language','oc_layout','oc_layout_module','oc_layout_route','oc_length_class','oc_length_class_description','oc_location','oc_manufacturer','oc_manufacturer_to_store','oc_marketing','oc_modification','oc_module','oc_option','oc_option_description','oc_option_value','oc_option_value_description','oc_order','oc_order_custom_field','oc_order_fraud','oc_order_history','oc_order_option','oc_order_product','oc_order_recurring','oc_order_recurring_transaction','oc_order_status','oc_order_total','oc_order_voucher','oc_osapi_last_modified','oc_product','oc_product_attribute','oc_product_description','oc_product_discount','oc_product_filter','oc_product_image','oc_product_option','oc_product_option_value','oc_product_recurring','oc_product_related','oc_product_reward','oc_product_special','oc_product_to_category','oc_product_to_download','oc_product_to_layout','oc_product_to_store','oc_recurring','oc_recurring_description','oc_return','oc_return_action','oc_return_history','oc_return_reason','oc_return_status','oc_review','oc_setting','oc_stock_status','oc_store','oc_tax_class','oc_tax_rate','oc_tax_rate_to_customer_group','oc_tax_rule','oc_tg_tglite_revolution_slider','oc_upload','oc_url_alias','oc_user','oc_user_group','oc_voucher','oc_voucher_history','oc_voucher_theme','oc_voucher_theme_description','oc_weight_class','oc_weight_class_description','oc_zone','oc_zone_to_geo_zone']
I cannot spot where I've gone wrong. Maybe I Will try it on a diferent server next.

Don't create your JSON string manually, just use json_encode, thats why this function exists anyway:
First is gather all the table names inside a container first, finish the gathering, the loop and the whole bit, after your done with that, then encode it.
$result = $conn->query($tablesGetSQL);
$JSONStringArray = array(); // initialize container
while($row = $result->fetch_assoc()) {
$JSONStringArray[] = $row['table_name']; // push all table names
}
// finally, encode
$JSONStringArray = json_encode($JSONStringArray);
$conn->close();
return $JSONStringArray;

You are getting two copies because of this line
$JSONStringArray .= substr($JSONStringArray, 0, -1) . ']';
You do the .= which is doing the substr, and adding it to the original, you should just do an =
ie, should just be:
$JSONStringArray = substr($JSONStringArray, 0, -1) . ']';
As a side note, there's no need to build a JSON string, PHP has a built in method to generate the json string. Instead you can do
$data = array();
while($row = $result->fetch_row())
{
$data += $row; // append returned array to the data array, since you wanted it future proof incase you added more columns to the SELECT query
}
// close connection
return json_encode($data);

Related

Running MySQL queries inside a loop

I want to run multiple mysql queries in a loop. Maybe this the wrong approach but thats why I'm asking.
Example:
A user submits a array of userinput and i want loop through it an perform multiple mysql queries. If I hardcode the ID it works but if I set the ID as a VAR it dosen't. When using a VAR it alway shows a result with the last entry.
Best, Tim
if(isset($_POST['list'])){
$list=$_POST['list'];
$list_arr=explode(PHP_EOL, $list);
$list_arr_len=count($list_arr);
for ($i=0; $i < $list_arr_len; $i++) {
echo $list_arr[$i]."<br>";
$result = mysqli_query($con,"SELECT col FROM table where id='$list_arr[$i]'");
$row=mysqli_fetch_array($result,MYSQLI_NUM);
echo $row[0]."<br>";
}
mysqli_close($con);
}
You can do it in one query like this:
if(!empty($_POST['list'])){
$list=$_POST['list'];
$list_arr=explode(PHP_EOL, $list);
$list_id=implode("', '", array_map('mysqli_real_escape_string', $list_arr));
$result = mysqli_query($con,"SELECT col FROM table where id IN ('{$list_id}')");
while($row=mysqli_fetch_array($result,MYSQLI_NUM)) {
echo $row[0]."<br>";
}
mysqli_close($con);
}
in this example no matter which type of colum for id u use
Create PDO object and set it in exception mode
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
try
{
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
echo 'Connection failed: ' . $e->getMessage();
}
You are posting a comma separated list (I'd post an array but what the hell), so we're going to simply parse the string into integers and stick it in MySQL's IN clause
if(isset($_POST['list']))
{
$list = str_replace(["\r", "\n"], "", $_POST['list']);
$numbers = strpos($list, ',') !== false ? explode(",", $list) : (int)$list;
// This can probably bet written nicer, the idea is to have each number explicitly typecast to int so it's safe to stick in a query directly
// Basically, you want "1,2,3,4,5" without the possibility of having some bad input here
if(is_array($numbers))
{
$numbers = implode(",", array_map(function($number)
{
return (int)$number;
}, $numbers));
}
// And the nice, one liner, where you query and fetch the records which are now in the array called $records
$records = $pdo->query(sprintf("SELECT * FROM your_table WHERE id IN(%s)", $numbers))->fetchAll(PDO::FETCH_ASSOC);
}
Note: I didn't test the code so don't copy paste it, it most likely contains errors. I wrote the answer to show how easy it is to use PDO and retrieve results easily, in one liner.
I think this shall work:
$result = mysqli_query($con,"SELECT col FROM table where id=".mysqli_real_escape_string($list_arr[$i])."");
First Create a string of all the ids and use IN(String of Ids) in your query and store all the data corresponding to id in an array.
$stringIds = "";
for ($i=0; $i < $list_arr_len; $i++)
{
if (is_null($stringIds))
{
$stringIds = '"' . $list_arr[$i] . '"';
}
else
{
$stringIds .= ',"' . $list_arr[$i] . '"';
}
}
$resulSet = mysqli_query($con, ""SELECT col FROM table where id='?'"");
while($row = mysqli_fetch_assoc($resulSet))
{
mainArray[$row['id']] = $row;
}
Now, your able to fetch all your data from the array using foreach loop and please use PDO to avoid SQL Injection.
Problem was:
\n \r
This c0de works for me now ( also IN('') might be the better idea ):
if(isset($_POST['list'])){
$list=$_POST['list'];
//echo $list;
$replace = array("\n", "\r");
$id = str_replace( $replace, ",", $list);
$id_arr = explode(",", $id);
$id_arr_len = count($id_arr);
for ($i=0; $i < $id_arr_len; $i++) {
# code...
$result = mysqli_query($con,"SELECT col1,col2 FROM table where id='$id_arr[$i]'");
while($row = mysqli_fetch_assoc($result)){
echo $row['col1'].': ';
echo $row['col2'].'<br/>';
}
}
}

Putting MySQL data into an array

I've tried for a couple of days to get all of the data from a MySQL column and put it inside an array, formatted in the following way:
$aSpam= array
( '.info'=> 'i'
, 'anal'=> 'i'
, 'anus'=> 'i'
, 'arse'=> 'i'
)
I've managed to echo it out formatted properly as you can see here: http://www.yourgrumble.com/phpbbforum/getSpam.php
with the following PHP code:
<?php
$servername = "localhost";
$username = "username";
$password = "pass";
$dbname = "db";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sql = "SELECT `SpamWord` FROM spamWords";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
$counter = 0;
while($row = $result->fetch_assoc()) {
if($counter){
echo ", '" . $row["SpamWord"]. "'=> 'i'";
$counter++;
} else {
echo "'" . $row["SpamWord"]. "'=> 'i'";
$counter++;
}
}
} else {
echo "Error!";
}
$conn->close();
?>
I've read and tried more than 10 solutions found in the web and here at stackoverflow, however none of them worked. I've really got desperate and I cannot get through this without your help guys.
Edit
For example I tried with this solution, but it didn't work:
while ($row = mysql_fetch_array($result))
{
$new_array[$row['id']]['SpamWord'] = $row['SpamWord'];
}
foreach($new_array as $array)
{
echo $array['SpamWord'].'<br />';
}
Thank you all in advance,
Denis Saidov
Try like below:-
$sql = "SELECT `SpamWord` FROM spamWords";
$result = mysqli_query($conn ,$sql) or die(mysqli_error($conn));
$resultArray = array(); // create an array
if ($result->num_rows > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
$resultArray[$row["SpamWord"]] = 'i'; // assing value
}
} else {
echo "Error!";
}
echo "<pre/>";print_r($resultArray); // print array
$conn->close();
Note: Here you will get your original array containing all SpamWord values comes from database.thanks
PHP array's are like dictionnaries (a list of key/value pairs)
First, before your loop, create your array empty:
$new_array = Array();
while...
Then for each column, you append the column value as a new key for the array
$new_array[$row['SpamWord']] = "i";
As in your example, I put "i" as the value for each array's row.

How to use rows of Mysql array in PHP function?

I have a function in PHP and I would like to export an array from my MYSQL Database and then use the rows in a loop to do some stuff with them.
$DB_Server = "XXX.XXX.XXX.XXX";
$DB_Username = "XXXX";
$DB_Password = "XXXXX";
$DB_Database = "XXXXX";
$conn = new mysqli($DB_Server, $DB_Username, $DB_Password, $DB_Database);
$query = "Select Name, Wert from test.DBPBX";
function show(array $options) {
global $showresult, $master, $conn, $query;
$result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($result)) {
$cnlongname = $row["Name"];
$usercontent = $row["Wert"];
$cn = $cnlongname;
$options['config']->value = 1;
$config = $options["config"]->value;
$show = new SimpleXMLElement("<show/>");
$user = $show->addChild("user");
$user->addAttribute("cn", $cn);
if ($config)
$user->addAttribute("config", "true");
print "cmd: " . htmlspecialchars($show->asXML()) . "\n";
$showresult = $master->Admin($show->asXML());
print "result: " . htmlspecialchars($showresult) . "\n";
$mod = "text=".$usercontent;
$modify = new SimpleXMLElement("$showresult");
$user = $modify->user;
$path = explode("/device/hw/", $mod);
$srch = $user;
$nsegments = count($path);
$i = 1;
foreach ($path as $p) {
if ($i == $nsegments) {
// last part, the modification
list($attr, $value) = explode("=", $p);
$srch[$attr] = $value;
} else {
$srch = $srch->$p;
}
$i++;
}
$modify = new SimpleXMLElement("<modify>" . $user->asXML() . "</modify>");
print "cmd: " . htmlspecialchars($cmd = $modify->asXML()) . "\n";
// do it
$result = $master->Admin($cmd);
print "result: " . htmlspecialchars($result);
}
}
For $cn I would like to use $cnlongname (or $row["Name"]). And for $mod I would like to use $usercontent (or $row["Wert"]). However when I would like to use it I get an error after the first loop:
Warning: mysqli_fetch_assoc() expects parameter 1 to be
mysqli_result, string given in /sample.php on
line 175
Line 175 is:
while ($row = mysqli_fetch_assoc($result)) {
Can you please help me?
Inside your while loop you overwrite your result, therefore you lose your mysql result and cannot query it any more.
// do it
$result = $master->Admin($cmd);
Use a different variable there. :)

Echo text only if MySQL value matches

I have two rows in my MySQL data that I would like to have code echoed only if the MySQL row data is equal to '1' (as opposed to '0'). Here's the code so far, which seems to have some severe errors:
$query = "SELECT 162, 164 FROM search WHERE title = $title";
if ($result = $mysqli->query($query)) {
while ($row = $result->fetch_row()) {
if ($row["162"] = 1) {
echo '<div id="162link">1.6.2</div>';
}
}
if ($row["164"] = 1) {
echo '<div id="162link">1.6.2</div>';
}
}
}
$result->close();
}
$mysqli->close();
As it says in the code above the two rows are "162" and "164" in the database.
Use:
if ($row["162"] == 1)
Instead of:
if ($row["162"] = 1)
and:
if ($row["164"] == 1)
I tried for you something like this if it gives you some idea:
$host = "localhost";
$user = "myusername";
$pass = "mypassword";
$database = "WorldEngine";
$mysqli = new mysqli($host, $user, $pass, $database);
$title = "My Good News";
$query = "SELECT `162`, `164` FROM search WHERE title = '$title';";
if ($result = $mysqli->query($query)) {
$i = 0;
while ($row = $result->fetch_row()) {
if ($row["162"] == 1) {
echo '<div id="162link' . $i . '">1.6.2</div>';
}
if ($row["164"] == 1) {
echo '<div id="164link' . $i . '">1.6.4</div>';
}
$i++;
}
$result->free();
}
$mysqli->close();
The index $i is appended to the div ID in order to produce unique DOM element ID's in the HTML document. I would also suggest you to change your numerical column names into alphabet-starting names like c162, c164, ...
Hope this will help you.

Export large database to file without mysqldump, low memory footprint [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
memory usage export from database to csv in php
I am exporting a large database and wanted to know the best way to make it have a low memory footprint.
I realize that I must do this in cycles that have a time limit and use low memory, fetching say 100 rows at a time and saving the information to the file then redirect to start a new cycle starting from where it finished on the previous cycle.
I am wondering whats the best way buffer the data to file and not run out of memory, at present the script gets all data as a string then saves to file when it has finished getting all rows from the database. Some times it runs out of memory, hence the need to fix.
Do I use fwrite() on the data fetched from the database instead of putting into a var or use a temp file? If I use a temp file when do I merge/rename into the backup file?
Basically what is the best way for the script to export the database data into a file without getting the error "Fatal Error: PHP Allowed Memory Size Exhausted"?
function backup_tables($host, $user, $pass, $db, $tables = '*')
{
set_time_limit(0);
$mysqli = new mysqli($host,$user,$pass, $db);
if ($mysqli->connect_errno)
{
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$return = '';
$return .= "--\n";
$return .= "-- Database: `$db`\n";
$return .= "--\n\n";
$return .= "-- --------------------------------------------------------\n\n";
$numtypes = array(
'tinyint',
'smallint',
'mediumint',
'int',
'bigint',
'float',
'double',
'decimal',
'real'
);
// get all of the tables
if ($tables == '*')
{
$tables = array();
$result = $mysqli->query('SHOW TABLES');
while ($row = $result->fetch_row())
{
$tables[] = $row[0];
}
$result->close();
}
else
{
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
for ($z = 0; $z == 0; $z++)
{
echo $z.'<br>';
// cycle through tables
foreach ($tables as $table)
{
//
$typesarr = array();
$result = $mysqli->query("SHOW COLUMNS FROM `".$table."`");
while ($row = $result->fetch_assoc())
{
$typesarr[] = $row;
}
$result->close();
#echo '<h2>'.$table.'</h2>';
#print("<pre>" . print_r($typesarr, true). "</pre>");
// table structure dump
$return .= "--\n";
$return .= "-- Table structure for table `$table`\n";
$return .= "--\n\n";
$return.= 'DROP TABLE IF EXISTS `'.$table.'`;'."\n\n";
$result = $mysqli->query("SHOW CREATE TABLE `".$table."`");
$row = $result->fetch_array();
$return.= $row[1].";\n\n";
$result->close();
// table data dump
$return .= "--\n";
$return .= "-- Dumping data for table `$table`\n";
$return .= "--\n\n";
$result = $mysqli->query("SELECT * FROM `".$table."`");
$num_fields = $result->field_count;
if ($result->num_rows > 0)
{
// put field names in array and into sql insert for dump
$fields_str = '';
$fields = array();
$finfo = $result->fetch_fields();
foreach ($finfo as $val)
{
$fields_str .= '`'.$val->name.'`, ';
$fields[] = $val->name;
}
$fields_str = '('.rtrim($fields_str, ', ').')';
$return.= 'INSERT INTO `'.$table.'` '.$fields_str.' VALUES'."\n";
// cycle through fields and check if int for later use
for ($i = 0; $i < $num_fields; $i++)
{
// strip brackets from type
$acttype = trim(preg_replace('/\s*\([^)]*\)/', '', $typesarr[$i]['Type']));
$acttype = explode(' ', $acttype);
// build array, is field int or not
if (is_numeric(array_search($acttype[0], $numtypes)))
{
$numflag[$i] = 1;
}
else
{
$numflag[$i] = 0;
}
}
}
$x = 0;
$num_rows = $result->num_rows;
// cycle through table rows
while($row = $result->fetch_row())
{
$x++;
// cycle through rows fields
for($j=0; $j<$num_fields; $j++)
{
if (isset($row[$j]) and $j === 0) { $return .= '('; }
// field data has value or not NULL
if (isset($row[$j]))
{
// field data dump (INT)
if ($numflag[$j]==1)
{
#echo '(INT) '. $fields[$j].' = '.$row[$j].'<br>';
$return.= $mysqli->real_escape_string($row[$j]);
}
else
{
// field data dump values (empty string, NULL and INT)
$return.= "'".$mysqli->real_escape_string($row[$j])."'";
#echo $fields[$j]." = '".$mysqli->real_escape_string($row[$j])."'<br>";
}
}
else
{
// field data dump (NULL)
if (is_null($row[$j]))
{
$row[$j] = 'NULL';
#echo '(NULL) '. $fields[$j].' = '.$row[$j].'<br>';
$return.= $row[$j];
}
else
{
// field data dump (empty string)
$return.= "''";
}
}
if ($j<($num_fields-1)) { $return.= ', '; }
}
if ($x<$num_rows) { $return.= "),\n"; } else { $return .= ");\n"; }
#echo '<br>';
}
#echo 'Rows: '.$rows.'<br>';
#echo 'Iterations: '.$x.'<br>';
$return.="\n-- --------------------------------------------------------\n\n";
}
}
$result->close();
//save file
$handle = fopen('/db-backup-'.time().'.sql','a');
fwrite($handle,$return);
fclose($handle);
}
Examples welcome
Add MYSQLI_USE_RESULT as the resultmode parameter to the mysqli::query call in order to iterate over the results one row at a time, without transferring them all to PHP in one bunch. See also the documentation for mysqli::use-result.
Write each line directly to the output file, avoiding the $result variable. Combined with the above, this can lead to each row being fetched from the server and written to file, so PHP won't have to store more than one row at a time.
Recent versions of mysqldump by default have --opt enabled, which includes --quick which in turns indicates that rows are fetched one at a time, without buffering the whole table in memory. So the memory footprint of mysqldump already should be pretty low.
Are you sure that there are actually any problems when using mysqldump? If so, how do they manifest? Is mysqldump out of memory, or is it the mysql server, or something else entirely?

Categories