PHP - CSV to table not converting as expected - php

I am trying to create SQL INSERT statements from a CSV file. I have successfully opened and read the file. I have even output the file in a table format. However, the alterations I do in the for loop such as when $c == 0 do not work. It just outputs to the table exactly as it was in the csv file. That is what I am trying to change! To keep with that example, I am trying to make the name "John Doe" be "john" and "Doe". The CSV file has the names as one and I'd like to split into first and last.
Also, the phone numbers aren't changing either. The code to change them begins with $c == 5. The funny thing is when I put them into here: http://ideone.com/HfGXJk It works fine.
<?php
fgetcsv_PHP();
function fgetcsv_PHP()
{
if (($handle = fopen("guests.csv", "r")) !== FALSE)
{
$length = 1000;
$delimiter = ",";
$fname = array();
$lname = array();
$address = array();
$city = array();
$state = array();
$zip = array();
$phone = array();
$email = array();
//print opening table
echo "<table border='1'>\n";
while ( ( $data = fgetcsv( $handle, $length, $delimiter ) ) !== FALSE )
{
// Count number of array elements in $data
$num = count($data);
// Print opening table row HTML tag
echo "<tr>\n";
//loop through array
for ($c=0; $c < $num; $c++)
{
if ($c == 0)
{
$name = $c;
$name = explode(" ",$name);
$first = array_shift($name);
$last = array_pop($name);
array_push($fname, $first);
array_push($lname, $last);
echo "<td>".$data[$first]."</td>\n";
}
if ($c == 1)
{
array_push($address, $c);
echo "<td>".$data[$c]."</td>\n";
}
if ($c == 2)
{
array_push($city, $c);
echo "<td>".$data[$c]."</td>\n";
}
if ($c == 3)
{
array_push($state, $c);
echo "<td>".$data[$c]."</td>\n";
}
if ($c == 4)
{
array_push($zip, $c);
echo "<td>".$data[$c]."</td>\n";
}
if ($c ==5)
{
$phnum = $c;
$phnum = preg_replace('~[^0-9]~','',$phnum);
array_push($phone, $phnum);
echo "<td>".$data[$phnum]."</td>\n";
}
if ($c == 6)
{
array_push($email, $c);
echo "<td>".$data[$c]."</td>\n";
}
}
// Print closing table row HTML tag
echo "</tr>\n";
}
// Print close table HTML tag
echo "</table>";
// Close the file pointed to by $handle
fclose($handle);
}
}
?>

The part reading the name, sets $name to 0, explodes it at the non existing space, puts the 0 from the first element of the array (from the explode) in $first and outputs $data[$first] meaning $data[0] - the original value.
Refactored to PHP 5.5:
$file = new SplFileObject('guests.csv', 'r');
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(',', '"');
$converter = function($traversable) {
foreach ($traversable as $data) {
list($first, $last) = explode(' ', $data[0]);
$address = $data[1];
$city = $data[2];
$state = $data[3];
$zip = $data[4];
$phone = preg_replace('([^\d])', '', $data[5]);
$email = $data[6];
$result = array(
'first' => $first,
'last' => $last,
'address' => $address,
'city' => $city,
'state' => $state,
'zip' => $zip,
'phone' => $phone,
'email' => $email,
);
yield $result;
}
};
foreach ($converter($file) as $data) {
var_dump($data);
}

The code you posted to the other site is not the code you posted here. If that works, fine. It has little to do with this:
if ($c ==5)
{
$phnum = $c;
$phnum = preg_replace('~[^0-9]~','',$phnum);
array_push($phone, $phnum);
echo "<td>".$data[$phnum]."</td>\n";
}
Look at $phnum. The first thing you do is set it to $c, i.e 5. Then you remove all the non-numeric characters in 5, push the result onto an array which you don't appear to use, and output $data[$phnum], i.e. $data[5], your original data.

Related

php how to get whole line after spicific character from text file?

I have text file
name,name1
willhaveishere1
name,name2
willhaveishere2
name,name3
willhaveishere3
i want read it and return like that
$nn = name1
$ss = willhaveishere1
with my code i get only name1
my code is
$file1 = "file.txt";
$file = file($file1);
$count = count($file);
if($count > 0) {
$i = 1;
foreach($file as $row) {
$n = strstr($row, 'name,');
$cc = array("name,");
$dd = array("");
$nn = str_replace($cc, $dd, $n);
echo $nn;
$i++; } }
This is probably what you need
if($count > 0) {
foreach($file as $row) {
$pos = strpos($row, ',');
if($pos !== false){
echo substr($row, $pos + 1);
$nn[] = substr($row, $pos + 1);
} else {
echo $row;
$ss[] = $row;
}
}
}
EDIT
Yes, just loop through, but make sure both $nn and $ss has same count, which is depending on your file.
Also Note: mysql_* functions has been deprecated, so please use mysqli or PDO instead
$count = count($nn);
for($i=0; $i < $count; $i++){
$sql = "INSERT INTO users(name, line) VALUES('$nn[$i]', '$ss[$i]')"; mysql_query($sql);
}
EDIT 2
try this example:
$file = array(
0 => 'name,name1',
1 => 'willhaveishere1',
2 => 'name,name2',
3 => 'willhaveishere2',
4 => 'name,name3',
5 => 'willhaveishere3'
);
$count = count($file);
if($count > 0) {
foreach($file as $row) {
$pos = strpos($row, ',');
if($pos !== false){
$nn[] = substr($row, $pos + 1);
} else {
$ss[] = $row;
}
}
}
echo '<pre>';
$count = count($nn);
for($i=0; $i < $count; $i++){
$sql = "INSERT INTO users(name, line) VALUES('$nn[$i]', '$ss[$i]');";
echo $sql.PHP_EOL;
}
You can try this straightforward method:
if($fh = fopen("file.txt","r")){
$nameBefore = false;
//loop through every line of your file
while (!feof($fh)){
$line = fgets($fh);
//check if the name was detected in previous line
if ($nameBefore !== false)
{
//you have the set of name and line, do what you want
echo $nameBefore . ': ' . $line . '<br />';
$nameBefore = false;
}
else
{
//see if the line is made of two coma separated segments and the first one is 'name'
//Remember the name for the next line
$parts = explode(',', $line);
if (count($parts) == 2 && $parts[0] == 'name')
$nameBefore = $parts[1];
}
}
fclose($fh);
}
One option is to use strpos to find the first occurrence of the character in the line, and if found remove everything from the line before that position. This way you are left with only the part of the line you are interested in.
Code:
$character = ',';
$fileHandle = fopen('file.txt', 'r');
while (!feof($fileHandle)) {
// Retrieve the line from the file
$line = fgets($fileHandle);
// If the line contains the character
// Remove everything before the character
$charPos = strpos($line, $character);
if ($charPos !== false) {
$line = substr($line, $charPos + 1);
}
// Do something with the remainder of the line
echo $line . PHP_EOL;
}
fclose($fileHandle);
Output:
name1
willhaveishere1
name2
willhaveishere2
name3
willhaveishere3
If you wish to retrieve the following line, simply do another retrieve line call in your loop:
while (!feof($fileHandle)) {
// Retrieve two lines in one loop iteration
$lineOne = fgets($fileHandle);
$lineTwo = fgets($fileHandle);
}
Making sure to only apply the comma replace part on the first line. This can lead to problems though if your data is... inconsistent.
Hope this helps.

PHP Reading Lines from a Text File

I am trying to search a line in a text file and then print the following three lines. For example, if the text file has
1413X
Peter
858-909-9999
123 Apple road
then my PHP file would take in an ID ("1413X") through a form, compare it to lines in the text file - essentially a mock database - and then echo the following three lines. Currently, it is echoing only the phone number (with the second half of the numbers wrong??). Thanks for your help.
<?php
include 'SearchAddrForm.html';
$file = fopen("addrbook.txt", "a+");
$status = false;
$data = '';
if (isset($_POST['UserID']))
{
$iD = $_POST['UserID'];
$contact = "";
rewind($file);
while(!feof($file))
{
if (fgets($file) == $iD)
{
$contact = fgets($file);
$contact += fgets($file);
$contact += fgets($file);
break;
}
}
echo $contact;
}
fclose($file);
?>
It is better to set some flag that you found id and some counter to count lines after it to achieve your aim.
<?php
include 'SearchAddrForm.html';
// $file = fopen("addrbook.txt", "a+");
$file = fopen("addrbook.txt", "r");
$status = false;
$data = '';
if (isset($_POST['UserID']))
{
$iD = $_POST['UserID'];
$contact = "";
rewind($file);
$found = false;
$count = 1;
while (($line = fgets($file)) !== FALSE)
{
if ($count == 3) // you read lines you needed after you found id
break;
if ($found == true)
{
$contact .= $line;
$count++
}
if (trim($line) == $iD)
{
$found = true;
$contact = $line;
}
}
echo $contact;
}
fclose($file);
?>
This kind of example how you can achieve this. And as you see in comment you should use $contact .= value, not $contact += value.
Also instead of reading you can take the whole file in array line by line using function file.
And why are opening file for writing?
What I did:
<?php
//input (string)
$file = "before\n1413X\nPeter\n858-909-9999\n123 Apple road\nafter";
//sorry for the name, couldn't find better
//we give 2 strings to the function: the text we search ($search) and the file ($string)
function returnNextThreeLines($search, $string) {
//didn't do any check to see if the variables are not empty, strings, etc
//turns the string into an array which contains each lines
$array = explode("\n", $string);
foreach ($array as $key => $value) {
//if the text of the line is the one we search
//and if the array contains 3 or more lines after the actual one
if($value == $search AND count($array) >= $key + 3) {
//we return an array containing the next 3 lines
return [
$array[$key + 1],
$array[$key + 2],
$array[$key + 3]
];
}
}
}
//we call the function and show its result
var_dump(returnNextThreeLines('1413X', $file));

How do I put this array into csv or excel?

I can't figure out a way to do this and I really bad with working with arrays so I hope someone can help me.
I have array $stuck that just contains names, like this
$stuck = array('Daniel','Alex','alfredo','dina');
I am using sort to put the names in alphabetical order, like this
sort($stuck);
Now the thing is I want to put this array into a csv or excel file so the first letter of name will be the title and all the names with this letter will be under this title.
This is an example of what I am trying to accomplish
Here try this. I added comments between the code.
$csvArray = array();
$nameArray = array('Daniel','Alex','alfredo','dina');
//Create an array that can be used for creating the CSV
foreach($nameArray as $name)
{
$firstLetter = strtoupper(substr($name, 0,1));
$csvArray[$firstLetter][] = $name;
}
//Determine the subarray which have the must rules
$maxRuleCount = 0;
foreach($csvArray as $firstLetter => $nameArray)
{
if(count($nameArray) > $maxRuleCount)
{
$maxRuleCount = count($nameArray);
}
}
//Create the first rule (letters)
$csvContent = implode(';', array_keys($csvArray));
$csvContent .= "\r\n";
//Loop through the CSV array and create rules of the names
for($i = 0 ; $i < $maxRuleCount ; $i++)
{
foreach($csvArray as $firstLetter => $nameArray)
{
$csvContent .= #$csvArray[$firstLetter][$i].';';
}
$csvContent .= "\r\n";
}
//The hole csv content is in the $csvContent variable now
//If you want to print it you need to add the text/plain header because of the \r\n new line characters
header("Content-Type:text/plain");
echo $csvContent;
Ouput is:
D;A
Daniel;Alex;
dina;alfredo;
<?php
$stuck = array('Daniel','Alex','Dina','durban','eigor','alfredo','dina');
// associate names with first letters in a new array
foreach ($stuck as $name) {
$first_letter = strtoupper( substr( $name, 0, 1 ) );
$new_name_array[ $first_letter ][] = $name;
}
// store the first letter list in an array and sort it
$first_letters = array_keys( $new_name_array );
sort( $first_letters );
// sort the name lists
foreach( array_keys( $new_name_array ) as $letter ) {
sort( $new_name_array[$letter] );
}
// output csv header row
echo "'".implode( "','", $first_letters )."'\n";
// output the CSV name rows
$i = 0;
while ( true ) {
$row = array();
$is_row = false;
foreach( $first_letters as $letter ) {
$row[] = $new_name_array[ $letter ][ $i ];
if( ! empty( $new_name_array[ $letter ][ $i ] ) ) $is_row = true;
}
if( ! $is_row ) exit;
echo "'" . implode( "','", $row ) . "'\n";
$i++;
}
?>
Outputs quoted CSV:
'A','D','E'
'Alex','Daniel','eigor'
'alfredo','Dina',''
'','dina',''
'','durban',''
<?php
$stuck = array('Daniel','Alex','alfredo','dina', 'eigor', 'durban');
sort($stuck);
$sortedNames = array();
$maxEl = 0;
foreach ($stuck as $name) {
$name = strtolower($name);
$sortedNames[$name{0}][] = $name;
$maxEl = count($sortedNames[$name{0}]) < $maxEl ? $maxEl : count($sortedNames[$name{0}]);
}
$headers = array_keys($sortedNames);
$finalArray = array($headers);
for($i = 0; $i < $maxEl; $i++) {
$tmpRow = array();
foreach ($sortedNames as $names) {
$tmpRow[] = isset($names[$i]) ? $names[$i] : '';
}
$finalArray[] = $tmpRow;
}
$file = fopen("names.csv","w");
foreach ($finalArray as $line)
{
fputcsv($file,$line);
}
fclose($file);
Here is my attempt at this question:
$names = array('Daniel','Alex','alfredo','dina', 'eigor', 'falfoul', 'fiona');
natcasesort($names);
$columns = array();
foreach ($names as $name) {
$first = strtoupper(substr($name, 0, 1));
$columns[$first][] = $name;
}
// pad the columns so they all have the same number of rows
$maxRows = 0;
foreach ($columns as &$col) {
$numRows = count($col);
if ( $numRows > $maxRows) {
$maxRows = $numRows;
}
}
// pad the columns
foreach ($columns as &$column) {
$column = array_pad($column, $maxRows, '');
}
$firstLetter = array_keys($columns);
$numCols = count($firstLetter);
// transpose the columns array
$rows = array();
foreach ($columns as $csvCol) {
foreach ($csvCol as $k=>$n) {
$rows[$k][] = $n;
}
}
// pad the rows to ensure they all have the same number of
// columns
foreach ($rows as &$row) {
$row = array_pad($row, $numCols, '');
}
// add the title row to the rows
array_unshift($rows, $firstLetter);
$handle = fopen("names.csv", 'w');
foreach ($rows as $fRow) {
fputcsv($handle, $fRow);
}

PHP output number with leading zeros incorrectly

I have a line in a file like this:
0000000/BirthstoneEnsemble/f/0/1380152724
I explode by $pieces = explode("/", $line);
when I do echo $pieces[0] == "0000000" it returns false. I try to cast pieces[0] to string, but it is always incorrect.
function build_file_assoc() {
global $dir;
$assoc = [];
$file_assoc = file($dir . 'rsnjxdlxwxwun.dbt');
for($i = 0; $i < count($file_assoc) - 1; $i++) {
if($i > 0) {
list($parent_folder, $image_name, $tag, $size, $date) = explode("/", $file_assoc[$i]);
$assoc[] = [
'parent_folder' => (string)$parent_folder,
'image_name' => $image_name,
'tag' => $tag,
'size' => $size,
'date' => $date
];
}
}
return $assoc;
}
$g = build_file_assoc();
$first = $g[0]['parent_folder'];
echo $first == "0000000"; // false
file contents:
0000000/BirthstoneEnsemble/f/0/1380152724
0000000/Thumbs.db/a/83968/1384248954
0000000/bridal images for frame/f/0/1380152879
Try print array print_r($pieces) and you will see what is saved in specific fields after exlode.
If I run the code from your question, it works:
<?php
$line = '0000000/BirthstoneEnsemble/f/0/1380152724';
$pieces = explode("/", $line);
echo var_dump($pieces[0] == "0000000"); //true
?>
I would use the identical comparison operator and type cast pieces[0] as a string.
$line = '0000000/BirthstoneEnsemble/f/0/1380152724';
$pieces = explode('/',$line);
//echo '<pre>',print_r($pieces),'</pre>';
if((string)$pieces[0]==='0000000'){
echo true;
}else{
echo false;
}
// output: 1
var_dump
Check the actual value of your piece, since it's possible that you have a space or a tab character in there - var_dump will show it for you.
similar issue
Take a look at this post.

PHP Array only stores last value

Well, basically what this code does is grab some links from a source code of a website and send them to an mp3 player.
The big problem is on the get_link function, where i want to store the urls to an array. The section where im having problems is commented.
Sorry for posting all this code but the functions are connected to each others.
function getHost($db,$id){
if(isset($_GET['id'])){
$sql1 = "SELECT host FROM mixtape WHERE id=?";
$stm = $db->prepare($sql1);
$stm->execute(array($id));
$row1 = $stm->fetch(PDO::FETCH_ASSOC);
if($row1['host']=='host1'){
$sql2 = "SELECT link1 FROM faixa WHERE id_mixtape IN(SELECT id FROM mixtape WHERE id=?)";
$stm = $db->prepare($sql2);
$stm->execute(array($id));
$rows_affected = $stm->rowCount();
$array=array();
if (count($rows_affected) > 0) {
for($i=1; $i <= $rows_affected; $i++) {
$row2 = $stm->fetch(PDO::FETCH_ASSOC);
$url=$row2['link1'];
get_Link($db,$url,$i,$rows_affected,$array);
}
}
}
}
}
function get_Link($db,$url,$pos,$rows_affect,$array){
$find = 'url:';
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
$data = file_get_contents($url);
$data = explode("\n", $data);
for ($line = 0; $line < count($data); $line++) {
if (strpos($data[$line], $find) !== false) {
$link = preg_replace($reg_exUrl,"", $data[$line]);
$v[]=$link;
}
}
if($pos!=$rows_affect-1){
$url="mylink.com/".$link."|";
}else{
$url="mylink.com/".$link."&amp";
}
$array[$pos]=$url;
var_dump($array); // Here says that are 3 values in the array. True
if($pos==$rows_affect-1){
var_dump($array); // Here is only showing the last value in the array. Why?
player($db,$array);
}
}
function player($db,$array){
if(isset($_GET['id'])){
foreach($array as $i=>$item){
echo $item;
}
}
}
This piece of code:
$c=0;
for ($line = 0; $line < count($data); $line++) {
if (strpos($data[$line], $find) !== false) {
$link = preg_replace($reg_exUrl,"", $data[$line]);
$v[$c]=$link;
}
}
Should be like:
$c=0;
for ($line = 0; $line < count($data); $line++) {
if (strpos($data[$line], $find) !== false) {
$link = preg_replace($reg_exUrl,"", $data[$line]);
$v[$c]=$link;
$c = $c+1; //this is missing or $c++;
}
}
OR:
for ($line = 0; $line < count($data); $line++) {
if (strpos($data[$line], $find) !== false) {
$link = preg_replace($reg_exUrl,"", $data[$line]);
$v[]=$link; //That way works too
}
}
Miguelfsf, you must first learn about variable scope.
Your problem is, you created the $array=array() (the $array show be the $row2).
You declared a new variable, but you didn't used, the $array was just to tell you, declare your array that way
$row2=array().
After that you need to do
$row2[] = $stm->fetch(PDO::FETCH_ASSOC);
Why?
Because the assoc returns a associative array, then it will do
$array => {title => "last title} = $newData => {title => "new title"}
It will replace the value
Using the [] everytime you do this it'll create a new element.
Then
{
0 => { title => "title1"}
1 => { title => "title2"}
2 => { title => "title3"}
3 => { title => "title4"}
}

Categories