dont break line if data ending "\" while writing in csv in php - php

writing in csv file from database, if same id trying to append in "comments" coulmn with same row. but if from database value ending with "\" sign so next comments is writing in new line..if value is not ending with "\" for this working properly.
function cleanComments($string) {
$cleanstring = trim($string);
$returnstring = preg_replace("/\n/", "", $cleanstring);
return $returnstring;
}
function remove_special_char($string) {
$RemoveChars[] = "([,%+*¢£¥¤¡~©¦§¨ª«¬®¯°±²³´µ¶¸¹º»¿\[:^print:]])";
$ReplaceWith = "";
$text = preg_replace($RemoveChars, $ReplaceWith, $string);
return $text;
}
$comment_text = cleanComments($query_result['user_name'] . ':' . $query_result['comment']);
if ($counter == 1) {
$row['comment'].= remove_special_char($comment_text);
} else {
$row['comment'].= PHP_EOL . remove_special_char($comment_text);
}
if "\" this special character is ending with dont write in line in csv check my code anyting i missed? or any solution ?

i changed to this.
$comment_text = cleanComments(stripslashes($query_result['user_name'] . ':' . $query_result['comment']));
if ($counter == 1) {
$row['comment'].= remove_special_char($comment_text);
} else {
$row['comment'].= PHP_EOL . remove_special_char($comment_text);
}
its working properly now.

Related

PHP prevent extra empty line when writing text to file

I'm having a small issue regarding a foreach() loop and writing an array to a text file within.
The loop gives me the format in the file that I want but it also adds (as I was told) an unwanted empty line at the end of the file.
Here is my piece of code:
foreach($data_arr as $data => $input)
{ fwrite($fh, $data . ":" . $input . "\n") or die("something went wrong here"); }
Is there a way to prevent this from happening and not add the \n when it reaches the end of the array?
You can do something like this :
$data_array = ['c', 'h', "hf"];
$last = count($data_array) - 1; #size of the array
foreach($data_array as $data => $input)
{
$separator = $data == $last ? "" : "\n"; #if is last, then seperator isn't a back to line
fwrite($fh, $data . ":" . $input . $separator);
}
Just check if current index is the last one, then eventually add "\n" to the string
$last_index = count($data_arr)-1;
foreach ($data_arr as $data => $input)
{
$string = $data . ":" . $input;
if ($data != $last_index)
{
$string .= "\n";
}
fwrite($fh, $string) or die("something went wrong here");
}
Determining whether you are doing something for the last time, is cumbersome - for starters, you need to count your items, and then you need a loop index to compare to that count …
Much easier to determine, whether you are doing something for the first time. So just reverse your logic here - do not try to output “all lines, followed by a newline each, except the last one”, but instead, output “all lines preceded by a newline each, except the first one.”
You could use a simple boolean flag for that:
$is_first_line = true;
foreach($data_arr as $data => $input) {
fwrite($fh, ($is_first_line ? "" : "\n") . $data . ":" . $input);
$is_first_line = false;
}
Or you just append a variable before the line data all the time - and simply make that variable “empty” on the first iteration, and then fill it with a newline character for all the following ones:
$prefix = "";
foreach($data_arr as $data => $input) {
fwrite($fh, $prefix . $data . ":" . $input);
$prefix = "\n";
}

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";
}

Need help sorting this logic with JSON Pretty Print

Trying to pretty print json, and works fine, cept, seems to add an extra line when printing out an array of objects between each object array. Could use some help on the logic of this as I haven't touched this in awhile...
code for pretty printing it is as follows:
public function pretty_print($json_data, $line_numbers = true)
{
$return = '';
$space = 0;
$flag = false;
$json_data = trim($json_data);
$line = 1;
if (!empty($json_data)) {
if (!empty($line_numbers))
$return .= '<div class="line" data-line-number="' . $line . '">';
//loop for iterating the full json data
for($counter = 0; $counter < strlen($json_data); $counter++)
{
//Checking ending second and third brackets
if ($json_data[$counter] == '}' || $json_data[$counter] == ']')
{
$space--;
$line++;
$return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
$return .= str_repeat(' ', ($space*4));
}
//Checking for double quote(“) and comma (,)
if ($json_data[$counter] == '"' && ((!empty($counter) && $json_data[$counter-1] == ',') || ($counter > 1 && $json_data[$counter-2] == ',')))
{
$line++;
$return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
$return .= str_repeat(' ', ($space*4));
}
if ($json_data[$counter] == '"' && !$flag)
{
if ( (!empty($counter) && $json_data[$counter-1] == ':') || ($counter > 1 && $json_data[$counter-2] == ':' ))
$return .= ' <span class="json-property">';
else
$return .= '<span class="json-value">';
}
$return .= $json_data[$counter];
//Checking conditions for adding closing span tag
if ($json_data[$counter] == '"' && $flag) {
$return .= '</span>';
}
if ($json_data[$counter] == '"')
$flag = !$flag;
//Checking starting second and third brackets
if ($json_data[$counter] == '{' || $json_data[$counter] == '[')
{
$space++;
$line++;
$return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
$return .= str_repeat(' ', ($space*4));
}
}
if (!empty($line_numbers))
$return .= '</div>';
}
return !empty($return) ? trim($return) : json_encode(json_decode($json_data, true), JSON_PRETTY_PRINT);
}
But seems to parse the json with an extra <div class="line" data-line-number=""></div>
Here's an image of this and would like to get rid of the extra space between objects of the array in here if possible. Any help here, would really appreciate it.
Why the heck are you manually parsing JSON? That code is going to be incredibly difficult to reason about and maintain, especially if you come back to it later when a bug almost inevitably presents itself.
Rather than taking the difficult approach, consider instead doing the following:
1. Reformat the JSON so that it suits your needs. In this case, for example, you prefer to keep the closing and ending brackets of objects on the same line, rather than on separate lines.
2. Split the already-pretty-formatted JSON into separate lines.
3. Wrap the individual lines of your JSON in HTML.
4. Re-join the lines to get your final HTML.
function prettyWrapJson($json_data, $line_numbers = true) {
// Ensure that our JSON is in pretty format.
$json_data = json_encode(json_decode($json_data, true), JSON_PRETTY_PRINT);
// Modify the formatting so that adjacent closing and opening curly braces are on the same line.
// Note: we can add a similar line if we want to do the same for square brackets.
$json_data = preg_replace('/},\n +{/s', '},{', $json_data);
$line_number = 1;
// Coerce a boolean value.
$line_numbers = !empty($line_numbers);
// Split into an array of separate lines.
$json_lines = explode("\n", $json_data);
// Wrap the individual lines.
$json_lines = array_map(function($json_line) use ($line_numbers, &$line_number) {
// Check if this line contains a property name.
if(preg_match('/^( +"[^"]+"):/', $json_line, $matches)) {
// Similar result to explode(':', $json_line), but safer since the colon character may exist somewhere else in the line.
$parts = array($matches[1], substr($json_line, strlen($matches[1]) + 1));
// Wrap the property in a span, but keep the spaces outside of it.
$parts[0] = preg_replace('/^( +)/', '$1<span class="json-property">', $parts[0]) . '</span>';
// We only want to wrap the other part of the string if it's a value, not an opening brace.
if(strpos($parts[1], '{') === false && strpos($parts[1], '[') === false) {
// Similarly, wrap the value in a span, but keep the spaces outside of it.
$parts[1] = preg_replace('/^( +)/', '$1<span class="json-value">', $parts[1]) . '</span>';
}
// Re-join the string parts with the colon we stripped out earlier.
$json_line = implode(':', $parts);
}
// Finally, we can wrap the line with a line number div if needed.
if($line_numbers) {
$json_line = '<div class="line" data-line-number="' . ($line_number++) . '">' . $json_line . '</div>';
}
return $json_line;
}, $json_lines);
// Re-join the lines and return the result.
return implode("\n", $json_lines);
}
You may need to tinker with it slightly to get it formatted exactly to your preferences, but this should be much easier for you to work with.

PHP Search for a keyword (Action ') from a text file, prints all lines with that keyword, then counts how many lines are printed

So I just started learning PHP, and I wanted to search for a certain keyword (Action ') from a text file, then print all the lines with the keyword, then count all the lines printed.
Here's what I have so far:
<?php
$searchfor = 'ERR:';
echo "Lines found with the keyword " . "\"" . $searchfor . "\"" . "\n";
$array = array_filter(array_map(function($v){
return (stripos($v,'Action') !== false)? $v : false;
},array_filter(file('sampleTest.log',FILE_SKIP_EMPTY_LINES),function($v)
{
return (!empty(trim($v)));
})));
# This will implode the lines
echo (!empty($array))? implode('',$array) : '';
# This will count the array
echo "<br><br>Total lines printed: " . ((!empty($array))? count($array) : 0);
?>
So basically it looks for a certain keyword, in this case, "ERR:" from a certain text file, then prints all of the lines with "ERR:" and then it counts all the lines printed.
So what I wanted to do was look for the keyword (Action '). That's a space after the word Action and a single apostrophe. But it seems like it doesn't read the apostrophe(').
It prompts me this error in CMD:
' (T_CONSTANT_ENCAPSED_STRING) in C:\xampp\php\newTest.php on line 11
' (T_CONSTANT_ENCAPSED_STRING) in C:\xampp\php\newTest.php on line 11
Here is a simplified version of your code.
<?php
$searchfor = "Action '";
$file = file_get_contents("sampleTest.log");
$matches = array();
echo "Lines found with the keyword " . "\"" . $searchfor . "\"" . "\n";
$lines = explode(PHP_EOL,$file);
foreach($lines as $line){
if (strpos($line, $searchfor) !== false){
$matches[] = $line;
echo $line."<br>";
}
}
if(!empty($matches))
echo "<br><br>Total lines printed: ".count($matches);
else
echo "<br><br> No matches.";
?>
The script will read the log file and save each line separately. It then goes through all lines and if the search word is in the line, it prints the line and saves it to the matches array that is counted at the end of the script.

edit display of php recordSet output

The following code produces each result as text. I would like to add some html to each result, to change it from regular text to an href tag:
while (!$recordSet->EOF()) {
if ($pclass_name_list == '') {
$pclass_name_list .= $recordSet->fields['class_name'];
} else {
$pclass_name_list .= ',' . $recordSet->fields['class_name'];
}
$recordSet->MoveNext();
}
The above produces Result 1, Result 2. I'd like to change these to
Result 1
Result 2
etc..
If you are doing a simple addition of content into a string, you can either wrap the variable in curly braces and include it in a string that has double quotes (as below), or you can use the sprintf function to merge content into a template.
$pclass_name_list = array();
while (!$recordSet->EOF()) {
$current_class_name = $recordSet->fields['class_name'];
$pclass_name_list[] = "{$current_class_name}";
$recordSet->MoveNext();
}
$pclass_name_list = implode(", ", $pclass_name_list);
Maybe:
if ($pclass_name_list == '') {
$pclass_name_list .= '' . $recordSet->fields['class_name'] . '';
} else {
$pclass_name_list .= ', ' . $recordSet->fields['class_name'] . '';
}

Categories