Input and output format with PHP and SQLSRV - php

I have a fairly specific scenario that I'm struggling with. The frustration is that it shouldn't even be complicated!
I have a SQL database and I'm connecting to it using PHP + SQLSRV. The database structure is quite straight forward and currently has 2 varchar columns (ColumnA and ColumnB for this example).
My task is to read the data from this table, allow the values to be edited in a form and write back to the database. This part is easy enough and is all working.
The challenge now is that the database values need to be written to my (currently empty) values.php file in the following format.
<?php
$output = array (
"Val1" => 'aaa',
"Val2" => 'bbb',
"Val3" => 'ccc',
);
?>
Ideally, I'd like this to be done at the time of the save to database command which I can do as part of an AJAX success process so that part shouldn't be an issue
I started working on the following process;
<?php
$sql = "SELECT ColumnA, ColumnB FROM Table";
$stmt = sqlsrv_query( $conn2, $sql );
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
$test[]= array($row['ColumnA'] ." => '". $row['ColumnB']."',");
$values = implode(PHP_EOL,$test);
}
$content = '<?php
$output = array ("'.$values.'");
?>';
file_put_contents("c:/jjj/values.php", $content);
?>
This gives me a lot of "Array to string conversion" errors and the file gets populated with;
<?php
$output = array ("
Array
Array
);
?>
Where am I going wrong here?
EDIT
After the various comments below, the current code reads as;
<?php
$sql = "SELECT ColumnA, ColumnB FROM Table";
$stmt = sqlsrv_query( $conn2, $sql );
$test = [];
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
$test[] = [$row['ColumnA'] => $row['ColumnB']];
}
$content = "<?php" . PHP_EOL;
$content .= "\t" . '$output = [' . PHP_EOL;
foreach($test as $key => $value) {
$content .= "\t\t\"{$key}\" => \"{$value}\"," . PHP_EOL;
}
$content .= "\t];" . PHP_EOL;
$content .= "?>";
file_put_contents("c:/jjj/values.php", $content);
?>
This results in 3 Array to string conversion errors (One for each row) and an output file that looks like this:
<?php
$output = [
"0" => "Array",
"1" => "Array",
"2" => "Array",
];
?>
I still can't find a way to export my DB table to a file in the correct format using PHP.

I think this will come closer to what you want:
To echo tabs as well you could use \t within the double quotes
$content = "<?php" . PHP_EOL;
$content .= "\t" . '$output = [' . PHP_EOL;
foreach($test as $key => $value) {
foreach ($value as $subkey => $subvalue) {
$content .= "\t\t\"{$subkey}\" => \"{$subvalue}\"," . PHP_EOL;
}
}
$content .= "\t];" . PHP_EOL;
$content .= "?>";

Related

Query produces data, but the export is blank

I was recently tasked to update some older sites from MySQL to MySQLi.
Though slow and steady, the update has been ok until I ran into an issue when exporting some data to an excel document.
This code was written by a previous developer. There's a lot going on in the file, and I hope I'm grabbing the part that is supposed to be creating the excel document:
<?php
$export = mysqli_query ( $session->connDB(),$sql ) or die ( "Sql error : " . mysqli_error( ) );
$fields = mysqli_num_fields ( $export );
$num_rows = mysqli_num_rows( $export );
$pattern = '/[A-Z0-9][A-Z0-9._-]+#[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}/i'; //email
$phonpat = '/(\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4})(( |-|\.)?[ext\.]+ ?\d+)|\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4}))/i'; //telephone
$phPat = '/([0-9]{3})([0-9]{3})([0-9]{4})/';
$vippatt = '/VIP/i';
for($f=0; $f<$fields; $f++){
$header.='"'.mysqli_fetch_fields($export, $f).'"'."\t";
}
for($i=0; $i<$num_rows; $i++){
for($x=0; $x<$fields; $x++){
$email = mysqli_fetch_assoc($export,$i,"EMAIL");
$phone = mysqli_fetch_assoc($export,$i,"PHONE");
$viprm = mysqli_fetch_assoc($export,$i,"VIP");
preg_match ($pattern, $email, $matches);
preg_match ($phonpat, $phone, $phoneno);
preg_match ($vippatt, $viprm, $vpmatch);
if(isset($matches[0])) {$emal=strtolower($matches[0]);} else {$emal="";}
if(isset($vpmatch[0])) {$vips=strtoupper($vpmatch[0]);} else {$vips="";}
if(isset($phoneno[0])) {$phne=preg_replace($phPat,'($1) $2-$3 ',formatPhone($phoneno[0],false,false));} else {$phne="";}
if(mysqli_fetch_fields($export, $x)=='EMAIL'){
$fld=$emal;
} else {
if(mysqli_fetch_fields($export, $x)=='PHONE'){
$fld=$phne;
} else {
if(mysqli_fetch_fields($export, $x)=='VIP'){
$fld=$vips;
} else {
if(mysqli_fetch_fields($export, $x)=='UNITS'){
$fld=1;
} else {
$fld = mysqli_fetch_assoc($export,$i,mysqli_fetch_fields($export, $x));
}
}
}
}
$data.= '"'.$fld.'"'."\t";
}
$data.="\n";
}
?>
Here is where the code checks if the data is blank or not, and then exports the spreadsheet:
<?php
if ($data == "") {
$data = "\nNo records found for your search parameters.\n\n".$sql;
} else {
echo "should show data";
}
global $time;
$time = time();
header("Content-Disposition: attachment; filename=CargoManagementCustomReport-$time.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";
?>
When the spreadsheet gets exported, I see "should show data". This tells me the $data variable obviously has data. It's just not getting into the spreadsheet.
If you'll notice in the above, I'm using mysqli_fetch_fields. This was used to replace mysql_field_name (in my attempt to update to MySQLi).
I also tried mysqli_fetch_field, but got the same results.
I am getting no errors, but the spreadsheet is still blank.
I can echo $sql to get the query, and I can run the query in the database and it returns data.
What am I doing wrong and how can I fix it?
That whole code is gibberish, so I hope I understood what it is that it was meant to do.
Here are the main problems:
mysqli_fetch_fields() takes only 1 argument and returns an array of objects. You can't cast an array to a string. I assume you wanted to get the field name.
mysqli_fetch_assoc() takes only 1 argument and returns an array of data in an associative array as the name suggests. It also moves the internal pointer to the next row every time it is called. You are trying to use it as if it was mysql_result().
Your nested loops are very messy. I replaced them with simple foreach loops and replaced the nested if statements with a switch. While I would normally stay away from such constructs, this is the easiest way to migrate this code.
After removing all the mysqli nonsense, the code is now readable. It iterates over every field of every row, applying some transformations to some fields and concatenating the result into a string.
Fixed code:
$conn = $session->connDB();
$export = mysqli_query($conn, $sql);
$pattern = '/[A-Z0-9][A-Z0-9._-]+#[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}/i'; //email
$phonpat = '/(\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4})(( |-|\.)?[ext\.]+ ?\d+)|\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4}))/i'; //telephone
$phPat = '/([0-9]{3})([0-9]{3})([0-9]{4})/';
$vippatt = '/VIP/i';
foreach (mysqli_fetch_fields($result) as $field) {
$header .= '"' . $field->name . '"' . "\t";
}
$data = '';
foreach ($export as $row) {
foreach ($rows as $fieldName => $value) {
switch ($fieldName) {
case 'EMAIL':
preg_match($pattern, $value, $matches);
$data .= '"' . (isset($matches[0]) ? strtolower($matches[0]) : '') . '"' . "\t";
break;
case 'PHONE':
preg_match($phonpat, $value, $phoneno);
$phne = "";
if (isset($phoneno[0])) {
$phne = preg_replace($phPat, '($1) $2-$3 ', formatPhone($phoneno[0], false, false));
}
$data .= '"' . $phne . '"' . "\t";
break;
case 'VIP':
preg_match($vippatt, $value, $vpmatch);
$data .= '"' . (isset($vpmatch[0]) ? strtolower($vpmatch[0]) : '') . '"' . "\t";
break;
case 'UNITS':
$data .= '"1"' . "\t";
break;
default:
$data .= '"' . $value . '"' . "\t";
break;
}
}
$data .= "\n";
}

SQL Query returns null?

I want to get all names of my products and push them into an array. If I use the SQL Query (SELECT name FROM wp_all_import_xml GROUP BY name) in phpmyadmin I get this:
But if I use the query in my script I get this array:
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
...)
So, the query must return null. But why? - Everything is correct!
I do not get any connection error or query error... Where is my error?
I already tried to decode the strings and I also tried $myTitles[] = $tmp. But it also doesn't work... Any ideas?
And because everything in the $myTitles array is null, the script always enters the if(!(in_array($title, $myTitles) condition and I cannot execute what I actual want... I can only execute this, if the array and the condition is really true!
<?php
if ( ! defined('ABSPATH') ) {
// Set up WordPress environment
require_once( dirname( __FILE__ ) . '/wp-load.php' );
}
unlink('deleteOldProducts.txt');
$myfile = fopen('deleteOldProducts.txt', "w");
$database_gk = new mysqli("localhost", "censored", "censored", "censored");
$database_jt = new mysqli("localhost", "censored", "censored", "censored");
$myTitles = array();
$string = "";
if($database_jt->connect_errno){
$string .= "+++Couldn't connect to database_jt!+++\n\n");
}
if($database_gk->connect_errno){
$string .= "+++Couldn't connect to database_gk!+++\n\n");
}
$values_jt = $database_jt->query("SELECT name FROM `wp_all_import_xml` GROUP BY name");
$string .= $database_jt->error . "\n";
while($rowj = $values_jt->fetch_assoc()){
$tmp = utf8_encode($row["name"]);
array_push($myTitles, $tmp);
$tmp = null;
}
$values_gk = $database_gk->query("SELECT `post_title` FROM `fWR6qIN_posts` where post_type = 'product' AND post_status = 'publish' GROUP BY `post_title`");
$string .= $database_gk->error . "\n";
$string .= "+++ Start of Check +++\n\nMein Array:\n" . var_export($myTitles, true) . "\n\n";
$i = 1;
while($row = $values_gk->fetch_assoc()){
$title = utf8_decode($row["post_title"]);
if(!(in_array($title, $myTitles))){
$string .= $i . ":\t" . $title . "\n";
$i = $i + 1;
}
$title = null;
}
$string .= "\n +++ End of Check! +++";
fwrite($myfile, $string);
fclose($myfile);
?>
Greetings and Thank You!
Your while isn't correct. On while you are using $rowj but on array_push you are using $row. You can try the following code instead:
while($row = $values_jt->fetch_assoc()) {
$myTitles[] = utf8_encode($row["name"]);
}
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
http://php.net/manual/en/function.array-push.php

Getting a random object from an array in PHP

First and foremost, forgive me if my language is off - I'm still learning how to both speak and write in programming languages. How I can retrieve an entire object from an array in PHP when that array has several key, value pairs?
<?php
$quotes = array();
$quotes[0] = array(
"quote" => "This is a great quote",
"attribution" => "Benjamin Franklin"
);
$quotes[1] = array(
"quote" => "This here is a really good quote",
"attribution" => "Theodore Roosevelt"
);
function get_random_quote($quote_id, $quote) {
$output = "";
$output = '<h1>' . $quote["quote"] . '.</h1>';
$output .= '<p>' . $quote["attribution"] . '</p>';
return $output;
} ?>
<?php
foreach($quotes as $quote_id => $quote) {
echo get_random_quote($quote_id, $quote);
} ?>
Using array_rand and var_dump I'm able to view the item in the browser in raw form, but I'm unable to actually figure out how to get each element to display in HTML.
$quote = $quotes;
$random_quote = array_rand($quote);
var_dump($quote[$random_quote]);
Thanks in advance for any help!
No need for that hefty function
$random=$quotes[array_rand($quotes)];
echo $random["quote"];
echo $random["attribution"];
Also, this is useless
<?php
foreach($quotes as $quote_id => $quote) {
echo get_random_quote($quote_id, $quote);
} ?>
If you have to run a loop over all the elements then why randomize hem in the first place? This is circular. You should just run the loop as many number of times as the quotes you need in output. If you however just need all the quotes but in a random order then that can simply be done in one line.
shuffle($quotes); // this will randomize your quotes order for loop
foreach($quotes as $qoute)
{
echo $quote["quote"];
echo $quote["attribution"];
}
This will also make sure that your quotes are not repeated, whereas your own solution and the other suggestions will still repeat your quotes randomly for any reasonably sized array of quotes.
A simpler version of your function would be
function get_random_quote(&$quotes)
{
$quote=$quotes[array_rand($quotes)];
return <<<HTML
<h1>{$quote["quote"]}</h1>
<p>{$quote["attribution"]}</p>
HTML;
}
function should be like this
function get_random_quote($quote_id, $quote) {
$m = 0;
$n = sizeof($quote)-1;
$i= rand($m, $n);
$output = "";
$output = '<h1>' . $quote[$i]["quote"] . '.</h1>';
$output .= '<p>' . $quote[$i]["attribution"] . '</p>';
return $output;
}
However you are not using your first parameter-$quote_id in the function. you can remove it. and call function with single parameter that is array $quote
Why don't you try this:
$quote = $quotes;
$random_quote = array_rand($quote);
$random = $quote[$random_quote];
echo '<h1>' . $random["quote"] . '.</h1><br>';
echo '<p>' . $random["attribution"] . '</p>';
Want to create a function:
echo get_random_quote($quotes);
function get_random_quote($quotes) {
$quote = $quotes;
$random_quote = array_rand($quote);
$random = $quote[$random_quote];
return '<h1>' . $random["quote"] . '.</h1><br>'.'<p>' . $random["attribution"] . '</p>';
}
First, you dont need the $quote_id in get_random_quote(), should be like this:
function get_random_quote($quote) {
$output = "";
$output = '<h1>' . $quote["quote"] . '.</h1>';
$output .= '<p>' . $quote["attribution"] . '</p>';
return $output;
}
And I cant see anything random that the function is doing. You are just iterating through the array:
foreach($quotes as $quote_id => $quote) {
echo get_random_quote( $quote);
}
According to http://php.net/manual/en/function.array-rand.php:
array_rand() Picks one or more random entries out of an array, and
returns the key (or keys) of the random entries.
So I guess $quote[$random_quote] should return your element, you can use it like:
$random_quote = array_rand($quotes);
echo get_random_quote($quote[$random_quote]);

updating a file in specific part only in php

I need to update a file using php
Sample file:
#Start#
No. of records: 2
Name: My name,
Age: 18,
Date: 2013-07-11||
Name: 2nd name,
Age: 28,
Date: 2013-07-11||
#End#
I need to edit 'No. of records' on each time I add another record on file. And another record needs to be before '#End#'
I'm using
$Handle = fopen($File, 'a');
$data = .......
fwrite($Handle, $Data);
to add records
How can I edit 'No. of records' & add data before '#End#'?
Instead of modifying the file I would parse it, change the data in PHP an rewrite the file after that.
To achieve this, I would firstly create a function that parses the input into php arrays:
function parse($file) {
$records = array();
foreach(file($file) as $line) {
if(preg_match('~^Name: (.*),~', $line, $matches)) {
$record = array('name' => $matches[1]);
}
if(preg_match('~^Age: (.*),~', $line, $matches)) {
$record ['age'] = $matches[1];
}
if(preg_match('~^Date: (.*)\|\|~', $line, $matches)) {
$record ['date'] = $matches[1];
$records [] = $record;
}
}
return $records;
}
Secondly I would create a function that flattens the arrays back into the same file format again:
function flatten($records, $file) {
$str = '#Start#';
$str .= "\n\n";
$str .= 'No. of records: ' . count($records) . "\n\n";
foreach($records as $record) {
$str .= 'Name: ' . $record['name'] . ",\n";
$str .= 'Age: ' . $record['name'] . ",\n";
$str .= 'Date: ' . $record['name'] . "||\n\n";
}
file_put_contents($file, $str . '#End#');
}
Then use it like this:
$records = parse('your.file');
var_dump($records);
$records []= array(
'name' => 'hek2mgl',
'age' => '36',
'date' => '07/11/2013'
);
flatten($records, 'your.file');
In case if file is relatively small (easily fits in memory), you can use file() function. It will return array, which you can iterate, etc.
If the file is larger, you'll need to read it in the loop using fgets(), writing data to the new temporary file and replacing original file with it after you're done

PHP inserting parsed values from text file into MySQL DB

I'm new to PHP and am trying to parse certain text from a txt file, and then insert the text into a MySQL database. So, let's get more specific. The file's format is as such, and it is repeated through the document end. the ellipses represent the previous and next tones.
...
[Tone27]
Atone = 707.3
Btone = 746.8
Btonelength = 3
Btonedebounce = 1
Description = Fire Department 1
mp3_Emails = email#address.com,email2#address.com,email3#address.com
amr_Emails = email2#textmessaging.com,email1#textmessaging.com
alert_command = c:\test.bat
post_email_command = c:\test2.bat
radio_frequency = 154.475
exclude_from = 13:25
exclude_to = 13:35
exclude_emails = email2#textmessaging.com,email2#address.com
...
What I want to do is parse the first items(e.g. '[tone27]') in each "tone block" from the file and insert it into the first field of a NEW row in the db. I then need to evaluate what comes before each line's " = ", for instance "Atone," and insert what comes after that line's " = ", for instance "707.3" into a field by that name. so, this row may look like this in the db:
$id | [tone27] | 707.3 |746.8 | 3 | 1 | Fire Department 1 |email1#x.com,email2#x.com,e...|...
and so on...
i've been able to isolate each thing by performing string functions, but am unsure of how to set up a loop that would insert each value properly. Here's the code I used to isolate them, but it's not helping at all with actually getting them into the database.
$txt_file = file_get_contents('config/tones.txt');
$rows = explode("\n", $txt_file);
foreach($rows as $row => $data)
{
$row_data = explode(' = ', $data);
if ((isset($row_data[0])) && ($row_data[0] !== " " )){
$info[$row]['attribute'] = $row_data[0];
$info_attribute = trim($info[$row]['attribute']);
}
if (isset($row_data[1])){
$info[$row]['value'] = $row_data[1];
$info_value = trim($info[$row]['value']);
//display data
echo 'Row ' . $row . ' Attribute: ' . $info_attribute . '<br />';
echo 'Row ' . $row . ' Value: ' . $info_value . '<br />';
} elseif (($info[$row]['attribute']) && (!empty($info_attribute))) {
echo "<br>";
echo 'Row ' . $row . ' Attribute: ' . $info_attribute . '<br />';
continue;
}
I'M A NOOB, NO DOUBT. I'M LOST. Thanks in advance for your help!!!
****|| EDIT ||****
Thanks for all of the excellent answers! here's what I've resultingly come up with. No queries yet, just a simple dash of the read portion of CRUD, but the code will be the same, only with queries. A big thanks to #leepowers for introducing me to the wonderful parse_ini_file() function.
foreach(parse_ini_file("config/tones.txt", true) as $k => $v){
extract($v, EXTR_SKIP);
echo "<br>";
echo $k . "<br>";
foreach($v as $sv => $ssv){
$lcase_sv = strtolower($sv);
if (trim($lcase_sv) == 'amr_emails'){
echo "sv: amr_Emails:<br>";
echo "ssv:<br>";
$eA = explode(',', trim($ssv));
foreach($eA as $eK => $eV){
echo "email" . filter_var($eK + 1, FILTER_SANITIZE_NUMBER_INT) . ": " . $eV . "<br>";
}
} elseif (trim($lcase_sv) == 'mp3_emails'){
echo "ssv:<br>";
$eA = explode(',', trim($ssv));
foreach($eA as $eK => $eV){
echo "email" . filter_var($eK + 1, FILTER_SANITIZE_NUMBER_INT) . ": " . $eV . "<br>";
}
}else {
echo "sv: " . $sv .", " . "s: " . $ssv . "<br>";
}
}
}
Use parse_ini_file to load the data structure into an array.
From there you can build and execute SQL statements:
$entries = parse_ini_file("config/tones.txt", true);
foreach ($entries as $section => $fields) {
extract($fields, EXTR_SKIP);
$sql = "INSERT INTO mytable (section, atone, btone) VALUES ($section, '$Atone', '$Btone'";
....
}
Of course, you'll need to prepare and escape the SQL statement before executing it.
parse_ini_file($source); return an associative array
$query = 'INSET INTO ... (key, value) VALUES (:key, :value)';
$stmt = DB::prepare($query);
foreach( parse_ini_file($source) as $key => $value )
{
$stmt->execute(array(':key' => $key, ':source' => $source));
}
This example use PDO
Just output of file in loop is:
foreach( parse_ini_file($source) as $key => $value )
{
echo $key; // Atone in first loop
echo $value; //707.3 in first loop
// BUT NOT USE THIS!!! use mysqli or PDO
mysql_query("INSERT INTO ... (key, value) VALUES ($key, $value)");
}
Here's another way to do it. Just need to modify it according to you needs (number of rows/credentials). It's better to use PDO.
$username = 'yourusername';
$password = 'yourpass';
try {
$conn = new PDO('mysql:host=127.0.0.1;dbname=yourdbname', $username, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'successfully connected';
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
foreach(parse_ini_file('yourfile.ini', true) as $row)
{
try {
// just adjust the number of columns accordingly
$stmt = $conn->prepare('insert into tablename values(?,?,?,?,?,?,?,?,?,?,?,?,?)');
// $row contains the values to insert
$stmt->execute($row);
echo 'rows affected' . $stmt->rowCount(); // 1
}catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}

Categories