Array to string conversion error line 11 - php

I get and error array to string conversion error on line 11
I need to compare $result array with $file array and then over write FILE with $result data. In other words, FILE and the data it contains is continuously being updated with $result
compare -> overwrite -> repeat at next execution.
Note: .db file is empty at first cycle but becomes populated at first write.
sample code with Array to string conversion error:
<?php
$id = $argv[1]; //variable for inbound
$result = array(
'return' => array(
array(1,2,3),
array(6,2,3),
array(3,2,3),
)
);
function getdiff($new, $old) {
$diff = array_intersect($new, $old);
return $diff;
}
$old = file_exists('1.db') ? json_decode(file_get_contents('1.db'), 1) : array();
$arrayDiffresult = getdiff( $result, $old);
file_put_contents('1.db', json_encode($result));
print_r(
getdiff($result, $old)
);
?>
I have a second method I have tried and I get the same error, at the comparison point line 9.
$result = array(
'return' => array(
array(1,2,3),
array(5,2,3),
array(3,2,3),
)
);
$lines = file("myDB.db");
$arrayDiffresult = array_diff ( $result['return'], $lines);
file_put_contents('myDB.db', print_r($result['return'], true));

I believe array_intersect is only used in one dimensional arrays, and it is attempting to treat the nested arrays as a string for equality comparison. However looking at the documentation show the function array_uintersect where you can write your own comparison function as a callback. You didn't provide much information as to what the requirements are but if you do I'd be happy to help

Related

PHP - How to re-order data within a multidimensional array with only one reliable preceding string?

I am being passed inconsistent data. The problem is the individual rows of $data_array are not consistently in the same sequence but each has a reliable "text:" preceding the value.
Each row contains about 120 elements of data. I only need 24 of those elements.
It's also possible one of the elements I need could be missing, such as "cost".
(I'm using php version 5.4)
-- Task:
Using $order_array, create a new $data_array_new by reordering the data in each "row" into the same sequence as $order_array.
If an elements is missing from a row insert "NA".
Once the elements are in the correct sequence the "text" is no longer required.
$order_array = array("price", "cost", "vol", "eps")
$data_array = Array (
$one = Array ("cost":43.40, "vol":44000, "eps":1.27, "price":65.00),
$two = Array ("eps":5.14, "price":33.14, "vol":657000),
$thr = Array ("vol":650000, "cost":66.67, "eps":1.33, "price":44.31),
);
The resulting ouput should appear with the data in this order: ("price", "cost", "vol", "eps")
$data_array_new = Array (
$one = Array (65.00,43.40,44000,1.27),
$two = Array (33.14,"NA",657000,5.14),
$thr = Array (44.31,66.67,650000,1.33),
);
$data_array_new = [];
foreach ($data_array as $index => $data) {
$data_array_new[$index] = [];
foreach ($order_array as $key) {
if (isset($data[$key])) {
$data_array_new[$index][] = $data[$key];
} else {
$data_array_new[$index][] = 'NA';
}
}
}
You can view the original incoming data here: https://api.iextrading.com/1.0/stock/market/batch?symbols=aapl,tsla,ge&types=quote,earnings,stats
Here is the answer from : Andreas
Use json_decode on the string with the second parameter true and you get a associative array as output.
$url = "https://api.iextrading.com/1.0/stock/market/batch?
symbols=aapl,tsla,ge&types=quote,earnings,stats";
$arr = json_decode(file_get_contents($url), true);
Var_dump($arr);
See here;
I copied the string from the page and posted it as $str.
https://3v4l.org/duWrI
Two steps is all that is needed.

Using a delimited string, how do I get an array item?

Here's an array:
array('csv'=>
array('path'=>'/file.csv',
'lines'=>array('line1',
'line2',
'line3'
)
)
)
As you can see, the array goes three levels deep.
Here are two strings:
1. 'csv/path'
2. 'csv/lines/0
Using / as the delimiter, string 1 will get '/file.csv' and string 2 will get 'line1'. I've been thinking about using a recursive function, but I just don't know yet how to go about it.
The idea is I won't know which array key I'm accessing. I'm working on creating a generic function that will take a string as input and return the respective value in the array.
Demo
Just iterate through each key from the string given, setting the new array to pull from as the found element in the given array. You should add error handling.
<?php
$array = array('csv'=>
array('path'=>'/file.csv',
'lines'=>array('line1',
'line2',
'line3'
)
)
);
echo extractData($array, 'csv/path'); // echoes /file.csv
echo extractData($array, 'csv/lines/0'); // echoes line1
function extractData($array, $string){
$keys = explode('/', $string);
$data = $array;
foreach ($keys as $key){
$data = $data[$key];
}
return $data;
}

PHP: Converting a String into a Nested Array

I'm using Laravel and am attempting to write an artisan command that accepts an argument, $content, that then needs to be transposed to an array. For example:
// An example of a value that is being passed in from the CLI and stored as $content
$content = "['div']['div'][0]['h2']['a']";
To clarify, $content is then being passed in as a function argument where it will be used to pull out the values from the actual result set. In other words, I'm receiving a response from an API and $content is the path to the values that I need to pull out of the response. For example, the hard coded version of the implementation looks like:
$result = $report['div']['div'][0]['h2']['a'];
Now, $result contains the values that I need to process. However, I'm trying to make this dynamic so I don't repeat myself each time I add in a new data source to check for reports. Currently, I have 4 functions each with hard-coded paths to the desired result; the goal is to make it so that I can pass in an argument that contains the path to the desired values and refactor my code so I only have the one function which accepts the path to the values as an argument.
I hope that clarifies the end-goal and why I'm only referencing keys, not a value.
Anyway, back to the problem at hand. I've attempted different variations of the following:
// Attempting to parse the string into an array
$arr = explode("]", trim(str_replace("[","",$content), "]"));
This results in the following array:
array (size=5)
0 => string ''div'' (length=5)
1 => string ''div'' (length=5)
2 => string '0' (length=1)
3 => string ''h2'' (length=4)
4 => string ''a'' (length=3)
But, what I need is for the array to be formatted like the following:
$array = ['div']['div'][0]['h2']['a']
I attempted to do a foreach($array as $element) over $arr and do an array_push for each element, but that resulted in the same output as $arr.
How can I loop over the string and parse it into an array? Additionally, I need 0 to remain as an index, and not be type casted as a string. And, one last note, the value of $content will be completely different each time, so I need it to be quite flexible. The only part that will remain constant is the [ and ] will always encapsulate the keys.
I'd love to hear how others would solve this seemingly trivial problem (I've taken a few years off from programming and apparently have forgotten more than I care to admit ;) ). I honestly thought that the str_replace and explode was going to provide me the result I was expecting...
But, after re-reading the php.net/explode doc, it's always going to cast each element as a string (thus overriding my 0 index), and I have no idea how to turn it into a nested array, instead of a simple, flat array.
I look forward to your advice and insight. Thanks.
EDIT:
Including the function that is making use of the arguments to help provide some greater clarity.
private function yql_check_website($url, $xpath, $content) {
require_once('../vendor/OAuth.php');
$statement = "select * from html where url='{$url}' and xpath='{$xpath}' ";
$cc_key = $this->key;
$cc_secret = $this->secret;
$url = "http://query.yahooapis.com/v1/public/yql";
$args = array();
$args["q"] = $statement;
$args["format"] = "json";
$consumer = new OAuthConsumer($cc_key, $cc_secret);
$request = OAuthRequest::from_consumer_and_token($consumer, NULL,"GET", $url, $args);
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL);
$url = sprintf("%s?%s", $url, OAuthUtil::build_http_query($args));
$url .= "&env=store://datatables.org/alltableswithkeys";
$ch = curl_init();
$headers = array($request->to_header());
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$rsp = curl_exec($ch);
$report = json_decode($rsp, true);
// Dynamically inspect the $report object for the xpath content
$result = $report . $content;
unset($report);
return $result;
}
So, $report contains the entire API response, but the only thing I need is the content that is provided in $report['div']['div'][0]['h2']['a'] (for this example, at least, the path is different for each report that I'm scraping). So, the reason I'm trying to convert the command line argument into an array is so that it can be used in the above code where $content is being called in order to navigate the API's response and return the values from that segment.
I hope that makes more sense. And, if there is a better way to achieve this end-goal, feel free to mention it. I may be taking the wrong approach...
Laravel has a few methods for array access that provide "dot" access to arrays, including array_get. The method prototype looks like this:
function array_get(array $array, string $key, mixed $default = null)
So, in your case, you could write:
$results = array_get($report, "div.div.0.h2.a");
You could just use preg_match_all here..
$content = "['div']['div'][0]['h2']['a']";
$expression = /\['([a-zA-Z0-9]+)\']/;
$results = preg_match_all( $expression, $content, $matches );
print_r( $matches );
If you have to have the array be like what you're saying, you could do something like this (for starters - this is a little ugly though as it is...)
// array( ['div']['div'][0]['h2']['a']
// visualizing...
// array( 'div' => array ( 'div' => 'array( "0" => array( "h2" => array( "a") ) ) ) );
function createDepth( $source, $currentKey, $nextDepth = null ) {
if( !is_array( $nextDepth ) ) {
$source[] = array( $currentKey => $nextDepth );
} else {
$nextKey = array_shift( $nextDepth );
$source[] = createDepth( array( $currentKey => array() ), $nextKey, $nextDepth );
}
return source;
}
// Edit: doh, unset the first key..
unset( $matches[0] );
// Continue from here.
$currentKey = array_shift( $matches );
$holder = array();
$final = createDepth( $holder, $currentKey, $matches);
print_r( $final );
Note: All the above is untested...
Is this what you want ?
$str = "['div']['div'][0]['h2']['a']";
$str = preg_split('/]\[/', substr(str_replace("'", "", $str), 1, -1));
print_r($str);
Array (
[0] => div
[1] => div
[2] => 0
[3] => h2
[4] => a
)

call_user_func_array + array_intersect with an array of array names, possible?

Sorry for the confusing title...
I need to perform an array_intersect() against a variable number of arrays. To do this it seems I need to use the call_user_func_array() function, however, this doesn't seem to be working and gives me the error:
Warning: array_intersect() [function.array-intersect]: Argument #1 is not an array in...
But, if I "print_r" the array to make sure then I see that it is an array:
Array ( [0] => arr_0 [1] => arr_1 )
My code (trimmed to just show the broken part):
$i = 0;
$arr_results = array();
foreach($arr_words as $word) {
$arrayname = "arr_".$i;
$$arrayname = array();
while ($row = mysql_fetch_assoc($search)) {
array_push($$arrayname, $row['id']);
}
array_push($arr_results, "$arrayname");
$i++
}
$matches = call_user_func_array('array_intersect',$arr_results);
In the full code I'm populating the arrays in the foreach loop with data obtained from sql queries.
From my comments:
"$arrayname" is a string, not an array. call_user_func_array will pass each element in $arr_results as argument to array_intersect. array_intersect expects arrays as arguments, but each item in $arr_results is a string, not an array.
All you have to do is create an array of arrays instead of array names:
$arr_results = array();
foreach($arr_words as $word) {
$ids = array();
while ($row = mysql_fetch_assoc($search)) {
$ids[] = $row['id'];
}
$arr_results[] = $ids;
}
$matches = call_user_func_array('array_intersect',$arr_results);
I turn $arrayname into an array with $$arrayname = array();
Right, you create a variable, lets say arr_0 which will point to array. But there is still a difference between the variable name arr_0 and the string containing the variable name "arr_0". You create an array of strings, and that just won't work. PHP does not know that the string contains a name of a variable. For example, consider this:
$arr = "arr_0";
echo $arr[0];
Based on your logic, it should output the first element of the array, but it does not, because $arr is a string, not an array, although it contains the name of a variable.
You'd have to use eval, but you really should not. You could also use variable variables again:
array_push($arr_results, $$arrayname);
that would work as well, but as I said, variable variables are confusing and in 99% of the cases, you are better of with an array.

Using arrays by reference

Why is the following code "crashing" in PHP?
$normal_array = array();
$array_of_arrayrefs = array( &$normal_array );
end( $array_of_arrayrefs )["one"] = 1; // choking on this one
The expected result is that the final code line appends $normal_array with key one having value 1 but there is no output what so ever, not even prints preceeding this code. In the real context of this scenario I use end() function to always append to the last array reference.
This doesn't crash, it just contains a syntax error:
end( $array_of_arrayrefs )["one"] = 1;
Unfortunately, you cannot treat function return values as arrays in PHP. You have to assign the value explicitly. Unfortunately, this doesn't work here because end makes a copy of the returned value.

Categories