Reading a CSV with file_get_contents in PHP - php

I am reading a 'kind' of csv file and exploding it and storing it in array.
The file I am reading has this structure
Id,Log,Res,File
mydb('Test1','log1','Pass','lo1.txt').
mydb('Test2','log2','Pass','lo2.txt').
mydb('Test3','log3','Pass','lo3.txt').
Now what I am trying to do is :
reading the last record in my database, get the Name, lets say in this case 'Test1' and then I am searching through my file and where I can find the position of 'Test1' and get the next lines in the file, extract the ID,s and add it to database.
I am getting the position of desired string in the file, but I am not sure how to get the next lines too.
Here's my code so far.
<?php
mysql_connect("localhost", "root", "") or die(mysql_error());
mysql_select_db("testing") or die(mysql_error());
$result = mysql_query("select ID from table_1 order by S_no DESC limit 1") or die(mysql_error());
$row = mysql_fetch_array( $result );
$a = $row['ID'];
echo 'Present Top Row is '.$a.'<br>';
$addresses = explode("\n", file_get_contents('\\\\fil1\\logs\\tes.pl'));
foreach($addresses as $val)
{
$pos = strstr($val, $a);
if ($pos === false) {
} else {
echo "The string <br> '$a' <br>was found in the string <br>'$val' <br>";
echo " and exists at position <br>$pos<br>";
}
}

Hope I understand you correctly. If so you could just set a flag once the item is found and then explode each line then on a ' character. The second value in the resultant array should then contain the id as per your example.
$addresses = explode("\n", file_get_contents('\\\\fil1\\logs\\tes.pl'));
$bFound = false;
foreach($addresses as $val)
{
if (!$bFound) {
$pos = strstr($val, $a);
if ($pos === false) {
} else {
echo "The string <br> '$a' <br>was found in the string <br>'$val' <br>";
echo " and exists at position <br>$pos<br>";
$bFound = true;
}
}
else {
$aCols = explode("'", $val);
$sId = $aCols[1];
// Now add Id as stored in $sId to DB here
}
}

If id is supposed to be unique, the traffic between the php process and the MySQL server is not the limiting factor and you have to parse each line anyway, you could create a unique index and let MySQL decide whether it accepts the record or not.
Simple example:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$pdo->exec('CREATE TEMPORARY TABLE foo (Id varchar(16),Log varchar(16),Res varchar(16),File varchar(16), unique key(Id))');
$stmt = $pdo->prepare('INSERT IGNORE INTO foo (Id,Log,Res,File) VALUES(?,?,?,?)');
$pattern = '/(?<=^mydb\().+(?=\)\.$)/';
$fp = 'dummy';
while ( false!==($row=dummy_fgets($fp)) ) {
if ( preg_match($pattern, $row, $m) ) {
$row = str_getcsv($m[0], ',', "'");
$stmt->execute($row);
echo $row[0], ' -> ', $stmt->rowCount(), "\n";
}
}
function dummy_fgets($dummy) {
static $data = array(
"mydb('Test1','log1','Pass','lo1.txt').\n",
"mydb('Test2','log2','Pass','lo2.txt').\n",
"mydb('Test3','log3','Pass','lo3.txt').\n",
// start again ...like you process the same file again + 1 new record
"mydb('Test1','log1','Pass','lo1.txt').\n",
"mydb('Test2','log2','Pass','lo2.txt').\n",
"mydb('Test3','log3','Pass','lo3.txt').\n",
"mydb('Test4','log3','Pass','lo3.txt').\n"
);
$rv = current($data);
next($data);
return $rv;
}
prints
Test1 -> 1
Test2 -> 1
Test3 -> 1
Test1 -> 0
Test2 -> 0
Test3 -> 0
Test4 -> 1

Related

Match csv filenames to table names and import

I have multiple csv files generated everyday with same name and they should be imported to Mysql database . I can import a single file to table where I have defined the csv file and table name before importing, but how to match the csv file to table names and import them. here is my code:
$conn = mysqli_connect($servername, $username, $password);
// Check connection
if (mysqli_connect_error()) {
echo "Connection failed!!!" .mysqli_connect_error();
exit();
}
else{
echo "Connected successfully \n";
}
$serverDir = $_SERVER['DOCUMENT_ROOT'];
//$filename = "OwlertonGreenIN.CSV";
echo getcwd();
print_r($filename);
//$table_name = strtolower( $filename );
//$filename = "$serverDir.$filename";
if (($handle = fopen($filename, 'r')) !== FALSE)
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE)
{
// print_r($data);
$import="INSERT into table name (`camera_name`,`plate`) values(`camera_name`,`plate`)";
}
I created functions for myself a while back that would essentially solve your problem if implemented correctly.
Only thing is I created them inside a DB class that uses/extends PDO and doesn't use mysqli. If you were to change how you connect to your database and use PDO, you could use the below class and utilize the insertQuery function that I made.
<?php
class DB extends PDO{
protected $host = "localhost";
protected $user = "admin";
protected $password = "";
public $connect;
public function __construct(string $dbname){
try{
$this->connect = new \PDO("mysql:host=".$this->host.";dbname=".$dbname, $this->user, $this->password);
$this->connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){ }
}
public function insertQuery(string $table, array $data){
try{
// declare our query peices
$half1 = "INSERT INTO `${table}` (";
$half2 = ") VALUES (";
// build both halfs of query w/ the keys of the array being used as the column name
foreach($data as $column => $v){
$half1 .= "${column}, ";
$half2 .= ":${column}, ";
}
// remove extra commas and spaces from the ends of our two halfs and then combine them
$query = substr($half1, 0, strlen($half1) - 2).substr($half2, 0, strlen($half2) - 2).")";
// prepare query
$prep = $this->connect->prepare($query);
// loop through & bind all values in array to the corresponding keys in our query
foreach($data as $column => $value){
if(is_string($value)){
$prep->bindValue(":${column}", $value, PDO::PARAM_STR);
}elseif(is_int($value)){
$prep->bindValue(":${column}", $value, PDO::PARAM_INT);
}elseif(is_bool($value)){
$prep->bindValue(":${column}", $value, PDO::PARAM_BOOL);
}
}
// execute query
$prep->execute();
// if row added, return true
if($prep->rowCount() > 0) return true;
// if not, return false
else return false;
}catch(PDOException $e){ return false; }
}
public static function csvParse($input, $callback = false){
$results = [];
$raw_array = (is_file($input)) ? array_map('str_getcsv', file($input)):array_map('str_getcsv', explode("\n", $input));
$array = array_splice($raw_array, 1, count($raw_array));
foreach($raw_array[0] as $c) $columns[] = $c;
foreach($array as $key0 => $val0) foreach($val0 as $key1 => $val1) $results[$key0][$columns[$key1]] = $val1;
if(is_callable($callback) && !empty($results)) call_user_func_array($callback, array($results));
elseif(!empty($results)) return $results;
else throw new Exception("Results Empty: Can not read the string or open file.");
}
}
$csv_str = "name,age,occupation,city\nCrimin4L,24,Programmer,New York\nMrAwesome,20,Gamer,Los Angeles";
// parse CSV file or string into a readable array (if file, use file location as parameter):
$csv_array = DB::csvParse($csv_str);
// print_r($csv_array) output:
/* Array
(
[0] => Array
(
[name] => Crimin4L
[age] => 24
[occupation] => Programmer
[city] => New York
)
[1] => Array
(
[name] => MrAwesome
[age] => 20
[occupation] => Gamer
[city] => Los Angeles
)
) */
// with that you can now use the DB::insertQuery function, but since it
// is a 2 dimentional array (multiple rows) you would need to loop
// through with a foreach
# start your database connection
$db = new DB("database_name_to_connect_into");
// Now loop through array with foreach
foreach($csv_array as $row){
# insert current row
$db->insertQuery("table_to_insert_data_into", $row);
}
/*
As long as the table column(s) match the key(s) in
the array, it should work flawlessly.
----
For this example, the table columns in the database
would need to be named: name, age, occupation, & city;
because that is what the array keys are named, basically
the array values are inserted into their corresponding table
columns by matching the array keys (if that any makes sense).
*/
?>
I can't really give you an example as its dealing with databases but if you'd like to play around with the code here it is in a sandbox: https://sandbox.onlinephpfunctions.com/c/20365
I'd use this:
$tablename = pathinfo($filename, PATHINFO_FILENAME);
Prepare an INSERT statement with placeholders:
$import="INSERT INTO `{$tablename}` (`camera_name`,`plate`) VALUES(?, ?)";
$stmt = $conn->prepare($import);
The tablename should be within back-ticks because you don't know if it contains whitespace or punctuation or an SQL reserved keyword.
Then execute that prepared statement for each row you read from the CSV file.
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE)
{
$stmt->bind_param('ss', $data[0], $data[1]);
$stmt->execute();
}
This may run pretty slowly, inserting one row at a time. You might like to read my presentation Load Data Fast! for more tips on performance improvement.

fetching one column values from multiple rows and Add comma in echo/print_r in php

I am trying to fetch multiple rows and want to show only one respective column values from each fetched row (while separated by commas or space between them).
I tried a number of approaches (commented code) but nothing happened.
$query="SELECT tests FROM p_tests WHERE app_id='$id' ";
//SELECT STRING_AGG(TaskName, ', ')
// FROM Tasks;
$run=mysqli_query($db,$query);
while ($run=mysqli_fetch_array($res)) {
// $tname=$run['tests'];
// echo $tname;
// $Var=implode(', ',$run['tests']);
// echo $Var;
// $run = implode(', ', array_column($run,0));
// echo $run;
//$test = array_column($run, 'tests');
// print_r($run);
// echo $run;
}
?>
If $run['tests'] is the specific column that you want to fetch from each row, then use the code as below:
$query="SELECT tests FROM p_tests WHERE app_id='$id' ";
//SELECT STRING_AGG(TaskName, ', ')
// FROM Tasks;
$run=mysqli_query($db,$query);
$arr = [];
while ($run=mysqli_fetch_array($res)) {
$tname=$run['tests'];
$arr[] = $tname;
}
$new_arr_comma = implode(',',$arr); // For comma seperated;
$new_arr_space = implode(' ',$arr); // For space seperated;
print_r($new_arr_comma);
print_r($new_arr_space);
?>
Something like....
<?php
$link = mysqli_connect ( 'localhost', 'user', 'pass', 'db' );
if ( $result = mysqli_query ( $link, "SELECT tests FROM p_tests WHERE app_id = '" . $id . "';", MYSQLI_USE_RESULT ) )
{
$data = array ( );
while ( $row = mysqli_fetch_assoc ( $result ) )
{
$data[] = $row['tests'];
}
mysqli_free_result ( $result );
echo implode ( ', ', $data );
}
?>

Pulling NHL Standings from XML Table with PHP

I'm working on a project in which I pull various statistics about the NHL and inserting them into an SQL table. Presently, I'm working on the scraping phase, and have found an XML parser that I've implemented, but I cannot for the life of me figure out how to pull information from it. The table can be found here -> http://www.tsn.ca/datafiles/XML/NHL/standings.xml.
The parser supposedly generates a multi-dimmensional array, and I'm simply trying to pull all the stats from the "info-teams" section, but I have no idea how to pull that information from the array. How would I go about pulling the number of wins Montreal has? (Solely as an example for the rest of the stats)
This is what the page currently looks like -> http://mattegener.me/school/standings.php
here's the code:
<?php
$strYourXML = "http://www.tsn.ca/datafiles/XML/NHL/standings.xml";
$fh = fopen($strYourXML, 'r');
$dummy = fgets($fh);
$contents = '';
while ($line = fgets($fh)) $contents.=$line;
fclose($fh);
$objXML = new xml2Array();
$arrOutput = $objXML->parse($contents);
print_r($arrOutput[0]); //This print outs the array.
class xml2Array {
var $arrOutput = array();
var $resParser;
var $strXmlData;
function parse($strInputXML) {
$this->resParser = xml_parser_create ();
xml_set_object($this->resParser,$this);
xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");
xml_set_character_data_handler($this->resParser, "tagData");
$this->strXmlData = xml_parse($this->resParser,$strInputXML );
if(!$this->strXmlData) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->resParser)),
xml_get_current_line_number($this->resParser)));
}
xml_parser_free($this->resParser);
return $this->arrOutput;
}
function tagOpen($parser, $name, $attrs) {
$tag=array("name"=>$name,"attrs"=>$attrs);
array_push($this->arrOutput,$tag);
}
function tagData($parser, $tagData) {
if(trim($tagData)) {
if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
$this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
}
else {
$this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
}
}
}
function tagClosed($parser, $name) {
$this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this- >arrOutput)-1];
array_pop($this->arrOutput);
}
}
?>
add this search function to your class and play with this code
$objXML = new xml2Array();
$arrOutput = $objXML->parse($contents);
// first param is always 0
// second is 'children' unless you need info like last updated date
// third is which statistics category you want for example
// 6 => the array you want that has wins and losses
print_r($arrOutput[0]['children'][6]);
//using the search function if key NAME is Montreal in the whole array
//result will be montreals array
$search_result = $objXML->search($arrOutput, 'NAME', 'Montreal');
//first param is always 0
//second is key name
echo $search_result[0]['WINS'];
function search($array, $key, $value)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, $this->search($subarray, $key, $value));
}
return $results;
}
Beware
this search function is case sensitive it needs modifications like match to
a percentage the key or value changing capital M in montreal to lowercase will be empty
Here is the code I sent you working in action. Pulling the data from the same link you are using also
http://sjsharktank.com/standings.php
I have actually used the same exact XML file for my own school project. I used DOM Document. The foreach loop would get the value of each attribute of team-standing and store the values. The code will clear the contents of the table standings and then re-insert the data. I guess you could do an update statement, but this assumes you never did any data entry into the table.
try {
$db = new PDO('sqlite:../../SharksDB/SharksDB');
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
echo "Error: Could not connect to database. Please try again later.";
exit;
}
$query = "DELETE FROM standings";
$result = $db->query($query);
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.tsn.ca/datafiles/XML/NHL/standings.xml');
$searchNode = $xmlDoc->getElementsByTagName( "team-standing" );
foreach ($searchNode as $searchNode) {
$teamID = $searchNode->getAttribute('id');
$name = $searchNode->getAttribute('name');
$wins = $searchNode->getAttribute('wins');
$losses = $searchNode->getAttribute('losses');
$ot = $searchNode->getAttribute('overtime');
$points = $searchNode->getAttribute('points');
$goalsFor = $searchNode->getAttribute('goalsFor');
$goalsAgainst = $searchNode->getAttribute('goalsAgainst');
$confID = $searchNode->getAttribute('conf-id');
$divID = $searchNode->getAttribute('division-id');
$query = "INSERT INTO standings ('teamid','confid','divid','name','wins','losses','otl','pts','gf','ga')
VALUES ('$teamID','$confID','$divID','$name','$wins','$losses','$ot','$points','$goalsFor','$goalsAgainst')";
$result= $db->query($query);
}

Getting data from mysql and creating a csv file issue

I want to extract some data and create a csv file. This is how my attributes table looks like. you can see it in the picture:
HERE
This is my code, what i tried:
$select = mysql_query("select * from attributes");
$final ="";
$i = 0;
while($row = mysql_fetch_array($select)) {
$id_produs = $row['id_produs'];
$n_attr = $row['nume_attr'];
$val = $row['val_attr'];
$final .= $id_produs . "%%" . $val . "%%";
$csv_array_attributes[$i] = $final;
$i++;
}
This is the part when i create the CSV file:
$file = fopen("attributes.csv", "w+");
foreach ($csv_array_attributes as $line) {
fputcsv($file, explode('%%', $line), "^", "`");
}
fclose($file);
AND this would be the wanted result: HERE. So, the nume_attr should be the header for every column in the csv and the val_attr should be the values for every nume_attr (see the image).
I tried many ways but I don't get this result from the image. I have to mention that my table "attributes" has more than 74000 rows.
This is the table structure:
CREATE TABLE `attributes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_produs` text NOT NULL,
`nume_attr` text NOT NULL,
`val_attr` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=673912 DEFAULT CHARSET=latin1;
/*Try following code */
$select = mysql_query("select * from attributes");
$i = 0;
$csv_array_attributes[$i]=array('sku','manufacturer_article','manufacturer');
$i++;
while($row = mysql_fetch_array($select)) {
$csv_array_attributes[$i] =array('sku'=>$row['id_produs'],'manufacturer_article'=>$row['nume_attr'],'manufacturer'=>$row['val_attr']);
$i++;
}
$file = fopen("attributes.csv", "w+");
foreach ($csv_array_attributes as $line) {
fputcsv($file,$line);
}
fclose($file);
Let's assume speed isn't the issue here and neither is concurrency, i.e. you just want the result now no matter how good, bad or ugly the solution is ;-)
First query all the attribute names via SELECT DISTINCT nume_attr FROM attributes
Store those names as keys of an array with empty string values, i.e. you should have an array like
$template = array(
'Manufacturer Article' => '',
'Manufacturer' => '',
...
)
Make a variable that stores the currently processed id_produs (start with false).
Make a variable that stores the current "csv"-record ( again start with false )
Query all records ordered by id_produs and iteratore over the result.
If the current record has a different id_produs than the "currently processed" write out the current "csv"-array and start anew with the template array created in the first step and the current id_produs as ...the current id_produs. For each record write the val_attr value to the key nume_attr in the csv array.
You will have to check/write the last record after the iteration.
/* try following code,and reply if it will helpful to you or not */
$select = mysql_query("select * from attributes");
$i = 0;
$i++;
while($row = mysql_fetch_array($select)) {
$csv_array_attributes[$row['id_produs']][$row['nume_attr']] =$row['val_attr'];
$i++;
}
$arraytempheader=array();
$arraytemp=array();
$arraytempheader[0]="";
$j=1;
foreach ($csv_array_attributes as $Colname=>$alline) {
if($j!=1)
{
foreach($arraytempheader as $key=>$val)
{
if($key!=$j && $key!=0)
$arraytemp[$Colname][$key]="";
}
}
foreach ($alline as $keyline=>$valline)
{
$arraytempheader[$j]=$keyline;
$arraytemp[$Colname][$j]=$valline;
$j++;
}
}
$file = fopen("attributes.csv", "w+");
fputcsv($file,$arraytempheader);
foreach ($arraytemp as $Colname=>$alline) {
$finalArray=array();
$finalArray[]=$Colname;
$finalArray=array_merge($finalArray,$alline);
fputcsv($file,$finalArray);
}
fclose($file);
Try to fix this in other way.
Here you select the attributes and store them into array
$select = mysql_query("select * from attributes");
$rezultat=array();
while($row = mysql_fetch_array($select)) {
$id_produs = $row['id_produs'];
$n_attr = $row['nume_attr'];
$val = $row['val_attr'];
//$final .= $id_produs . "%%" . $val . "%%";
$rezultat[] = array('id'=>$id_produs,'attr'=>$val);
}
And here you write them to the file.
$file = fopen("attributes.csv", "w+");
foreach ($rezultat as $line) {
fputcsv($file, $line, "^", "`");
}
fclose($file);

PHP: insert query result into array elements

How can I assign query result into array elements?
This is my code:
include('db.php');
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die("Database connection error");
mysql_select_db($dbname);
$query = "select * from test where value=20";
$result = mysql_query($query);
$vegetable_list = array('$rice', '$wheat', '$potato', '$pulses');
$i = 1;
while($row_result = mysql_fetch_row($result))
{
??????? = $row_result[$i];
$i++;
}
How can I assign the query result into the array? Let's say:
$rice = $row_result[1];
$wheat = $row_result[2];
$potato = $row_result[3];
How I can assign the values automatically?
Let try:
$vegetable_list= array('rice','wheat','potato','pulses'); //no $ symbol
while($row_result=mysql_fetch_row($result))
{
foreach($vegetable_list as $k => $v)
${$v} = $row_result[$k + 1]; //I think mysql_fetch_row should indexing from 0 -> n (not from 1)
}
Ok not sure but seems like you have a 150column x 20rows table that you want to convert into a two dimensional array. It is as simple as this:
$data = array( );
while( $row = mysql_fetch_assoc( $result ) )
{
// at this point, $row contains a single row as an associative array
// keys of this array consist of column names
// all you need to do is append $row to $data
$data[ ] = $row;
}
// $data is a two dimensional array
// $data[ 0 ] contains 1st row
// $data[ 1 ] contains 2nd row
// ...
// $data[ 0 ][ 'rice' ] contains rice column value for 1st row
// $data[ 0 ][ 'wheat' ] contains wheat column value for 1st row
// ...
// $data[ 1 ][ 'rice' ] contains rice column value for 2nd row
// $data[ 1 ][ 'wheat' ] contains wheat column value for 2nd row
// ...
// and so on
var_dump( $data );
Edited the code.
Here:
include('db.php');
$conn=mysql_connect($dbhost,$dbuser,$dbpass) or die("Database connection error");
mysql_select_db($dbname);
$query="select * from test where value=20";
$result=mysql_query($query);
if (!$result) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$vegetable_list= array( array () );
$rcols = mysql_query("SHOW COLUMNS FROM test");
if (!$rcols) {
echo 'Could not run query: ' . mysql_error();
exit;
}
if (mysql_num_rows($result) > 0) {
$i = 0;
$j = 0;
if (mysql_num_rows($result) == 0) {
echo "No rows found.";
} else {
while ($row = mysql_fetch_assoc($result)) {
while ($cols = mysql_fetch_assoc($rcols);) {
$vegetable_list[$i][$j] = $row[$cols['Field']];
$i++;
}
$j++;
}
}
} else {
//some error message
}
use switch case :
$i=1;
while($row_result=mysql_fetch_assoc($result))
{
switch($i) {
case 1 : $rice = $row_result[$i]; break;
case 2 : $wheat = $row_result[$i]; break;
}
$i++;
}
or you can do this :
$i=0;
$vegetable = array("rice", "wheat", "potato");
while($row_result=mysql_fetch_assoc($result))
{
$idx = 0;
foreach($row_result as $result){
${$vegetable[$i]}[$idx] = $result;
$idx++;
}
$i++;
}
then try to
var_dump($rice);
you should get array of your specific column.
The first thing is that, you dont need to make array element as variable.
You can simply write without dollar sign like : $rice as rice and so on.
$vegetable_list= array('rice', 'wheat', 'potato', 'pulses');
Now execute Select query to get the data from database
$query = "select * from test where value=20";
$result = mysql_query($query);
make while loop
while($row_result=mysql_fetch_row($result))
{
foreach($vegetable_list as $k => $v)
${$v} = $row_result[$k + 1];
from 0 -> n (not from 1)
}

Categories