Reading values from a file which contains associative array PHP - php

I need to read the content of a file called orders.log with PHP and use the variables. The log file is stored like this:
Array
(
[time] => 2099-99-99 00:00:00
[gateway] => Paypal
[gatewayOK] => Yes
[gatewayTransactionId] => XXXXXXX
[POST] => Array
(
[mc_gross] => 9.99
[protection_eligibility] => Eligible
[address_status] => confirmed
[payer_id] => XXXXX
[address_street] => XXXXX
[payment_date] => 00:00:00 Nov 11, 2018 PDT
[payment_status] => Completed
[charset] => windows-1252
)
)
I have tried reading it like this:
<?php
$orders=file_get_contents("orders.log");
echo $orders['time'];
echo $myarray[0]['gateway'];
echo $myarray[1]['mc_gross'];
?>
But the result does not work like intended. It throws "A" and "r" . Any help would be appreciated.

This assumes that each entry is 20 lines long, it reads in the log file and the splits it into 20 segments using array_chunk().
It then processes each segment, first splitting the lines by the => using explode() and adding the values to an associative array with the left hand side as the key. You can then use the key to access each value.
$input = file("log.txt", FILE_IGNORE_NEW_LINES);
$orders = array_chunk($input, 20);
foreach ( $orders as $order ) {
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
echo "gateway-".$split['gateway'].PHP_EOL;
echo "mc_gross-".$split['mc_gross'].PHP_EOL;
}
If you wanted a list of all orders...
$input = file("log.txt", FILE_IGNORE_NEW_LINES);
$orders = array_chunk($input, 20);
$orderList = [];
foreach ( $orders as $order ) {
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
$orderList[] = $split;
}
echo "gateway-".$orderList[0]['gateway'].PHP_EOL;
echo "mc_gross-".$orderList[0]['mc_gross'].PHP_EOL;
A third way which doesn't rely on the data being all the same format, this reads on a line by line basis and tries to work out the end of an element itself (just a line containing ))...
$fp = fopen("log.txt", "r");
$orderList = [];
$order = [];
while ( $line = fgets($fp)) {
// Remove extra data after content
$line = rtrim($line);
// If end of order (a line just starting with a ')')
if ( $line == ')' ) {
// Convert order into associative array
$split = [];
foreach ( $order as $line ) {
$info = explode("=>", $line);
if ( count($info) == 2){
$split[trim($info[0]," \t[]")] = trim ($info[1]);
}
}
// Add data to order list
$orderList[] = $split;
$order = [];
}
else {
// Add line to existing data
$order[] = $line;
}
}
print_r($orderList);
fclose($fp);

Related

How can i convert txt file to array

I have this sort of structure on a txt file.
[FILE_INFO]
[FIRST]
LOAD1= CPU
LOAD2 = RAM
[END_FIRST]
[GLOBAL_INDEX]
ELEC1=1235.12
GAZ2,1=1563.123
GAZ2,2= 28.56
[END_GLOBAL_INDEX]
[END_FILE_INFO]
What i need is to convert this txt structure to a php array , is this possible or txt structure is know ?
Array
(
[FILE_INFO] => Array
(
[FIRST] => Array
(
[LOAD1] => CPU
[LOAD2] => RAM
)
[GLOBAL_INDEX] => Array
(
[ELEC1] => 1235.12
[GAZ2] => Array
(
[1] => 1563.123
[2] => 28.56
)
)
)
)
Here is my approach:
$txt_file = file_get_contents("test.rt");
$rows = explode("\n", $txt_file);
$new_array = array(); $dimension = array();
foreach($rows as $row =>$data)
{
if($data[0] == "[" && substr($data, 0, 4) != "[END"){ // start
$output = str_replace( array('[',']') , '' , $data );
array_push($dimension, trim($output));
continue;
}else if(substr($data, 0, 4) == "[END"){ // end
$output = str_replace( array('[',']') , '' , $data );
array_pop($dimension);
continue;
}
$dim="";
foreach($dimension as $k=>$v){
$dim.= "['$v']";
}
$new_array.$dim[] = $data; // this is not working !!!!!
}
The problem is to position my cursor in the dimension of the array and insert the data
Try this:
<?php
$myfile = fopen("test.txt", "r");
// Iterate one line until end-of-file
while(!feof($myfile)) {
$text[] = fgets($myfile); // Add the data in an array
}
fclose($myfile);
print_r($text); // print the array
?>

how to convert a string with brackets to an array in php

I'm having a problem with this. I have a string that looks like this:
coilovers[strut_and_individual_components][complete_strut][][achse]
And i want to convert it to to array that looks like this:
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut]=> Array
(
[1] => Array
(
[achse] => some_value
)
[2] => Array
(
[achse] => some_value
)
)
)
)
is it possible?
Here is a quick implementation of a parser that will attempt to parse this string:
$input = 'coilovers[strut_and_individual_components][complete_strut][][achse]';
$output = array();
$pointer = &$output;
while( ($index = strpos( $input, '[')) !== false) {
if( $index != 0) {
$key = substr( $input, 0, $index);
$pointer[$key] = array();
$pointer = &$pointer[$key];
$input = substr( $input, $index);
continue;
}
$end_index = strpos( $input, ']');
$array_key = substr( $input, $index + 1, $end_index - 1);
$pointer[$array_key] = array();
$pointer = &$pointer[$array_key];
$input = substr( $input, $end_index + 1);
}
print_r( $output);
Essentially, we are iterating the string to find matching [ and ] tags. When we do, we take the value within the brackets as $array_key and add that into the $output array. I use another variable $pointer by reference that is pointing to the original $output array, but as the iteration goes, $pointer points to the last element added to $output.
It produces:
Array
(
[coilovers] => Array
(
[strut_and_individual_components] => Array
(
[complete_strut] => Array
(
[] => Array
(
[achse] => Array
(
)
)
)
)
)
)
Note that I've left the implementation of [] (an empty array key) and setting the values in the last index (some_value) as an exercise to the user.
Well I've found an another answer for it and it looks like this:
private function format_form_data(array $form_values) {
$reformat_array = array();
$matches = array();
$result = null;
foreach($form_values as $value) {
preg_match_all("/\[(.*?)\]/", $value["name"], $matches);
$parsed_product_array = $this->parse_array($matches[1], $value["value"]);
$result = array_push($reformat_array, $parsed_product_array);
}
return $result;
}
private function parse_array(array $values, $value) {
$reformat = array();
$value_carrier_key = end($values);
foreach (array_reverse($values) as $arr) {
$set_value_carrier = array($arr => $reformat);
if($arr == $value_carrier_key) {
$set_value_carrier = array($arr => $value);
}
$reformat = empty($arr) ? array($reformat) : $set_value_carrier;
}
return $reformat;
}
where array $form_values is:
Array
(
[name] => '[coilovers][strut_and_individual_components][complete_strut][][achse]',
[value] => 'some_value'
)
No. If you evaluate the string you will get invalid PHP.
If you want to store a PHP Array as string and get it loaded back as PHP Array, have a look at serialize and unserialize functions.
Of course you can build an array from your string, but you'll have to write a parser.
The solution I propose:
function format_form_data(array $data) {
$matches = array();
$result = [];
foreach($data as $key => $value) {
preg_match_all("/\[(.*?)\]/", $key, $matches);
$matches = array_reverse($matches[1]);
$matches[] = substr( $key, 0, strpos($key, '['));;
foreach ($matches as $match) {
$value = [$match=>$value];
}
$result = array_replace_recursive($result, $value);
}
return $result;
}

Query string like parameters regex

From a text like:
category=[123,456,789], subcategories, id=579, not_in_category=[111,333]
I need a regex to get something like:
$params[category][0] = 123;
$params[category][1] = 456;
$params[category][2] = 789;
$params[subcategories] = ; // I just need to know that this exists
$params[id] = 579;
$params[not_category][0] = 111;
$params[not_category][1] = 333;
Thanks everyone for the help.
PS
As you suggested, I clarify that the structure and the number of items may change.
Basically the structure is:
key=value, key=value, key=value, ...
where value can be:
a single value (e.g. category=123 or postID=123 or mykey=myvalue, ...)
an "array" (e.g. category=[123,456,789])
a "boolean" where the TRUE value is an assumption from the fact that "key" exists in the array (e.g. subcategories)
This method should be flexible enough:
$str = 'category=[123,456,789], subcategories, id=579, not_in_category=[111,333]';
$str = preg_replace('#,([^0-9 ])#',', $1',$str); //fix for string format with no spaces (count=10,paginate,body_length=300)
preg_match_all('#(.+?)(,[^0-9]|$)#',$str,$sections); //get each section
$params = array();
foreach($sections[1] as $param)
{
list($key,$val) = explode('=',$param); //Put either side of the "=" into variables $key and $val
if(!is_null($val) && preg_match('#\[([0-9,]+)\]#',$val,$match)>0)
{
$val = explode(',',$match[1]); //turn the comma separated numbers into an array
}
$params[$key] = is_null($val) ? '' : $val;//Use blank string instead of NULL
}
echo '<pre>'.print_r($params,true).'</pre>';
var_dump(isset($params['subcategories']));
Output:
Array
(
[category] => Array
(
[0] => 123
[1] => 456
[2] => 789
)
[subcategories] =>
[id] => 579
[not_in_category] => Array
(
[0] => 111
[1] => 333
)
)
bool(true)
Alternate (no string manipulation before process):
$str = 'count=10,paginate,body_length=300,rawr=[1,2,3]';
preg_match_all('#(.+?)(,([^0-9,])|$)#',$str,$sections); //get each section
$params = array();
foreach($sections[1] as $k => $param)
{
list($key,$val) = explode('=',$param); //Put either side of the "=" into variables $key and $val
$key = isset($sections[3][$k-1]) ? trim($sections[3][$k-1]).$key : $key; //Fetch first character stolen by previous match
if(!is_null($val) && preg_match('#\[([0-9,]+)\]#',$val,$match)>0)
{
$val = explode(',',$match[1]); //turn the comma separated numbers into an array
}
$params[$key] = is_null($val) ? '' : $val;//Use blank string instead of NULL
}
echo '<pre>'.print_r($params,true).'</pre>';
Another alternate: full re-format of string before process for safety
$str = 'count=10,paginate,body_length=300,rawr=[1, 2,3] , name = mike';
$str = preg_replace(array('#\s+#','#,([^0-9 ])#'),array('',', $1'),$str); //fix for varying string formats
preg_match_all('#(.+?)(,[^0-9]|$)#',$str,$sections); //get each section
$params = array();
foreach($sections[1] as $param)
{
list($key,$val) = explode('=',$param); //Put either side of the "=" into variables $key and $val
if(!is_null($val) && preg_match('#\[([0-9,]+)\]#',$val,$match)>0)
{
$val = explode(',',$match[1]); //turn the comma separated numbers into an array
}
$params[$key] = is_null($val) ? '' : $val;//Use blank string instead of NULL
}
echo '<pre>'.print_r($params,true).'</pre>';
You can use JSON also, it's native in PHP : http://php.net/manual/fr/ref.json.php
It will be more easy ;)
<?php
$subject = "category=[123,456,789], subcategories, id=579, not_in_category=[111,333]";
$pattern = '/category=\[(.*?)\,(.*?)\,(.*?)\]\,\s(subcategories),\sid=(.*?)\,\snot_in_category=\[(.*?)\,(.*?)\]/';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3);
print_r($matches);
?>
I think this will get you the matches out... didn't actually test it but it might be a good starting point.
Then you just need to push the matches to the correct place in the array you need. Also test if the subcategories string exists with strcmp or something...
Also, notice that I assumed your subject string has that fixe dtype of structure... if it is changing often, you'll need much more than this...
$str = 'category=[123,456,789], subcategories, id=579, not_in_category=[111,333]';
$main_arr = preg_split('/(,\s)+/', $str);
$params = array();
foreach( $main_arr as $value) {
$pos = strpos($value, '=');
if($pos === false) {
$params[$value] = null;
} else {
$index_part = substr($value, 0, $pos);
$value_part = substr($value, $pos+1, strlen($value));
$match = preg_match('/\[(.*?)\]/', $value_part,$xarr);
if($match) {
$inner_arr = preg_split('/(,)+/', $xarr[1]);
foreach($inner_arr as $v) {
$params[$index_part][] = $v;
}
} else {
$params[$index_part] = $value_part;
}
}
}
print_r( $params );
Output :
Array
(
[category] => Array
(
[0] => 123
[1] => 456
[2] => 789
)
[subcategories] =>
[id] => 579
[not_in_category] => Array
(
[0] => 111
[1] => 333
)
)

PHP CSV string to array

I'm trying to parse a CSV string to an array in PHP. The CSV string has the following attributes:
Delimiter: ,
Enclosure: "
New line: \r\n
Example content:
"12345","Computers","Acer","4","Varta","5.93","1","0.04","27-05-2013"
"12346","Computers","Acer","5","Decra","5.94","1","0.04","27-05-2013"
When I try to parse it like this:
$url = "http://www.url-to-feed.com";
$csv = file_get_contents($url);
$data = str_getcsv($csv);
var_dump($data);
The last and first element are concatenated in one string:
[0]=> string(5) "12345"
...
[7]=> string(4) "0.04"
[8]=> string(19) "27-05-2013
"12346""
How can I fix this? Any help would be appreciated.
Do this:
$csvData = file_get_contents($fileName);
$lines = explode(PHP_EOL, $csvData);
$array = array();
foreach ($lines as $line) {
$array[] = str_getcsv($line);
}
print_r($array);
It will give you an output like this:
Array
(
[0] => Array
(
[0] => 12345
[1] => Computers
[2] => Acer
[3] => 4
[4] => Varta
[5] => 5.93
[6] => 1
[7] => 0.04
[8] => 27-05-2013
)
[1] => Array
(
[0] => 12346
[1] => Computers
[2] => Acer
[3] => 5
[4] => Decra
[5] => 5.94
[6] => 1
[7] => 0.04
[8] => 27-05-2013
)
)
I hope this can be of some help.
You should use fgetcsv. Since you cannot import a file as a stream because the csv is a variable, then you should spoof the string as a file by using php://temp or php://memory first:
$fp = fopen("php://temp", 'r+');
fputs($fp, $csvText);
rewind($fp);
Then you will have no problem using fgetcsv:
$csv = [];
while ( ($data = fgetcsv($fp) ) !== FALSE ) {
$csv[] = $data;
}
fclose($fp)
$data will be an array of a single csv line (which may include line breaks or commas, etc), as it should be.
Caveat: The memory limit of php://temp can be controlled by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes. (the default is 2 MB) http://www.php.net/manual/en/wrappers.php.php
Handy oneliner:
$csv = array_map('str_getcsv', file('data.csv'));
I have used following function to parse csv string to associative array
public function csvToArray($file) {
$rows = array();
$headers = array();
if (file_exists($file) && is_readable($file)) {
$handle = fopen($file, 'r');
while (!feof($handle)) {
$row = fgetcsv($handle, 10240, ',', '"');
if (empty($headers))
$headers = $row;
else if (is_array($row)) {
array_splice($row, count($headers));
$rows[] = array_combine($headers, $row);
}
}
fclose($handle);
} else {
throw new Exception($file . ' doesn`t exist or is not readable.');
}
return $rows;
}
if your csv file name is mycsv.csv then you call this function as:
$dataArray = csvToArray(mycsv.csv);
you can get this script also in http://www.scriptville.in/parse-csv-data-to-array/
A modification of previous answers using array_map.
Blow up the CSV data with multiple lines.
$csv = array_map('str_getcsv', explode("\n", $csvData));
Slightly shorter version, without unnecessary second variable:
$csv = <<<'ENDLIST'
"12345","Computers","Acer","4","Varta","5.93","1","0.04","27-05-2013"
"12346","Computers","Acer","5","Decra","5.94","1","0.04","27-05-2013"
ENDLIST;
$arr = explode("\n", $csv);
foreach ($arr as &$line) {
$line = str_getcsv($line);
}
If you need a name for the csv columns, you can use this method
$example= array_map(function($v) {$column = str_getcsv($v, ";");return array("foo" => $column[0],"bar" => $column[1]);},file('file.csv'));
If you have carriage return/line feeds within columns, str_getcsv will not work.
Try https://github.com/synappnz/php-csv
Use:
include "csv.php";
$csv = new csv(file_get_contents("filename.csv"));
$rows = $csv->rows();
foreach ($rows as $row)
{
// do something with $row
}
You can convert CSV string to Array with this function.
function csv2array(
$csv_string,
$delimiter = ",",
$skip_empty_lines = true,
$trim_fields = true,
$FirstLineTitle = false
) {
$arr = array_map(
function ( $line ) use ( &$result, &$FirstLine, $delimiter, $trim_fields, $FirstLineTitle ) {
if ($FirstLineTitle && !$FirstLine) {
$FirstLine = explode( $delimiter, $result[0] );
}
$lineResult = array_map(
function ( $field ) {
return str_replace( '!!Q!!', '"', utf8_decode( urldecode( $field ) ) );
},
$trim_fields ? array_map( 'trim', explode( $delimiter, $line ) ) : explode( $delimiter, $line )
);
return $FirstLineTitle ? array_combine( $FirstLine, $lineResult ) : $lineResult;
},
($result = preg_split(
$skip_empty_lines ? ( $trim_fields ? '/( *\R)+/s' : '/\R+/s' ) : '/\R/s',
preg_replace_callback(
'/"(.*?)"/s',
function ( $field ) {
return urlencode( utf8_encode( $field[1] ) );
},
$enc = preg_replace( '/(?<!")""/', '!!Q!!', $csv_string )
)
))
);
return $FirstLineTitle ? array_splice($arr, 1) : $arr;
}
Try this, it's working for me:
$delimiter = ",";
$enclosure = '"';
$escape = "\\" ;
$rows = array_filter(explode(PHP_EOL, $content));
$header = NULL;
$data = [];
foreach($rows as $row)
{
$row = str_getcsv ($row, $delimiter, $enclosure , $escape);
if(!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}

Parse Unserialized array

i have a unserialized array
like this
Array (
[status] => 1
[msg] => Transaction Fetched Successfully
[transaction_details] => Array (
[100002982] => Array (
[mihpayid] => 4149968
[request_id] => 635788
[bank_ref_num] => NINETE.31845.28052012
[amt] => 3295.00
[disc] => 0.00
[mode] => CC
[retries] => 0
[status] => success
[unmappedstatus] => captured
)
)
)
i want to parse this array
so that i can get the value to status ie Success
how i can do that
$success = $array['transaction_details']['100002982']['status'];
$arr['transaction_details']['100002982']['status']
The PHP documentation has a user comment which suggests a method to parse the output of print_r (similar to the above). It can be found here: http://www.php.net/manual/en/function.print-r.php#93529
Here is a copy of the source code found at the above link:
<?php
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position in $in)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// recursively see if the parsed out value is an array too
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
?>
I have not tested the above function.

Categories