Parse ODATA query uri into PHP array - php

I have a client calling my web service written in PHP. While calling it, the client application gives a little query string to it. I want to parse this string into an array. So with the given example query within an url, I have started doing this:
Url: $select=substringof("customer", tolower(toupper(bla))),test$filter=Name%20eq%20'test'%20and%20toupper(Name)$skip=10$top=2$orderby=day(time)%20desc
.
<?php
function parseOdataRequest($request)
{
$expression = array();
// Fetch parameters
$params = explode('$', $request);
// Leave empty parameter name alone
unset($params[0]);
$params = array_values($params);
// Check every parameter
for($i = 0; $i < count($params); $i++)
{
// every parameter has to be a name=value pair!
$param = explode('=', $params[$i]);
if(!(count($param) == 2))
throw new Exception("Invalid parameter. Providence must be name=value");
// Validate parameter name
if(in_array($param[0], $this->validParams))
{
$parseParam = 'parse' . ucfirst(strtolower($param[0]));
$expression[$param[0]] = $this->$parseParam($param[1]);
}
else
throw new Exception("Unkown parameter '" . $param[0] . "'");
}
var_dump($expression);
}
?>
As a result, I have the following $expression:
array (size=5)
'select' => null
'filter' => null
'skip' => null
'top' => null
'orderby' => null
What I want is something like the following:
array (size=5)
'select' =>
array (size=2)
'substringof' =>
array (size=2)
0 => string 'customer' (length=8)
'tolower' =>
array (size=1)
'toupper' =>
array (size=1)
0 => string 'bla' (length=3)
0 => string 'test' (length=4)
'filter' =>
array (size=3)
0 =>
array (size=3)
0 => string 'Name' (length=4)
1 => string 'eq' (length=2)
2 => string ''test'' (length=6)
1 => string 'and' (length=3)
2 =>
array (size=3)
'toupper' =>
array (size=1)
0 => string 'Name' (length=4)
0 => string 'eq' (length=2)
1 => string ''TEST'' (length=6)
'skip' => int 10
'top' => int 2
'order' =>
array (size=1)
0 =>
array (size=2)
'day' =>
array (size=1)
0 => string 'time' (length=4)
0 => string 'desc' (length=4)
I tried different things, but never was successful. I would appreciate something like an approach to solve this problem.

Related

String to Nested Array

Hi i would like to ask if there is any good way to make Nested Array from few strings like in example but when i add NEW STRING it should append
it looks like some kind of tree
String
TEXT1|||TEXT2|||TEXT3 ....
into
[TEXT1 => [TEXT2 => [TEXT3] ] ]
new String
TEXT1|||AAA222|||AAA333
mew array with old one
[TEXT1 => [TEXT2 => [TEXT3 => null], AAA222 => [AAA333 => null] ] ]
string is generated from this array indexes are levels in "tree"
array (size=5)
0 =>
array (size=2)
'a' => string 'Motoryzacja' (length=11)
'b' => string '' (length=0)
1 =>
array (size=2)
'a' => string 'Części samochodowe' (length=20)
'b' => string '' (length=0)
2 =>
array (size=2)
'a' => string 'Części karoserii' (length=18)
'b' => string '' (length=0)
3 =>
array (size=2)
'a' => string 'Błotniki' (length=9)
'b' => string '' (length=0)
4 =>
array (size=2)
'a' => string 'Maski' (length=5)
'b' => string '' (length=0)
This is what I came up with:
//recursive function to build the array
function buildArray(Array $input, $output=[]){
$len = count($input);
if ($len > 0){
$key = array_shift($input);
//if there is more in the array, then we need to continue building our array
if (($len - 1) > 0){
$output[$key] = buildArray($input,$output);
}
else {
$output[$key] = NULL;
}
}
return $output;
}
//converts string input with ||| delimiter into nested Array
function stringToArray(String $input){
$arr = explode('|||', $input);
$output = buildArray($arr);
return $output;
}
$arr = stringToArray("TEXT1|||TEXT2|||TEXT3");
$arr2 = stringToArray("TEXT1|||AAA222|||AAA333");
var_dump(array_merge_recursive($arr,$arr2));

Swap two values in string(s) and sort by second value in php?

I have string like this:
EUR-USD,USD-EUR,SEk-CAD
I want to make this to an array and sort by second currency and I want to the result to be
SEk-CAD,USD-EUR,EUR-USD
(Sorted by CAD, EUR and USD)
This is my attempt and it works, but I'm wondering if I'm not "overdoing" this? Anyone has an easier/better solution to achieve this?
Second currency
Create an array of currency pairs:
array (size=3)
0 =>
array (size=2)
0 => string 'EUR' (length=3)
1 => string 'USD' (length=3)
1 =>
array (size=2)
0 => string 'USD' (length=3)
1 => string 'EUR' (length=3)
2 =>
array (size=2)
0 => string 'SEk' (length=3)
1 => string 'CAD' (length=3)
Reverse order of currencies pairs in above array and put them into a non mutlidimensional array:
array (size=3)
0 => string 'USD-EUR' (length=7)
1 => string 'EUR-USD' (length=7)
2 => string 'CAD-SEk' (length=7)
Sort the array (with sort() ) and glue that array into a new string
string 'CAD-SEk,EUR-USD,USD-EUR' (length=23)
Make an array of currency pairs from the newly created string:
array (size=3)
0 =>
array (size=2)
0 => string 'CAD' (length=3)
1 => string 'SEk' (length=3)
1 =>
array (size=2)
0 => string 'EUR' (length=3)
1 => string 'USD' (length=3)
2 =>
array (size=2)
0 => string 'USD' (length=3)
1 => string 'EUR' (length=3)
Reverse order of currencies pairs in above array and put them into a non mutlidimensional array:
array (size=3)
0 => string 'SEk-CAD' (length=7)
1 => string 'USD-EUR' (length=7)
2 => string 'EUR-USD' (length=7)
Glue the array together into a final string:
string 'SEk-CAD,USD-EUR,EUR-USD' (length=23)
Try this:
$currency_string = "EUR-USD,USD-EUR,SEk-CAD";
$currency_array = explode(",", $currency_string);
function compare($a, $b) {
$a = explode("-", $a);
$b = explode("-", $b);
if ($a[1] === $b[1]){
return 0;
}
return ($a[1] < $b[1]) ? -1 : 1;
}
usort($currency_array, "compare");
$final_currency_string = implode(",", $currency_array);
echo $final_currency_string; // Prints SEk-CAD,USD-EUR,EUR-USD
Hope this helps.

Add entries together based on key in array PHP

As you can see I have a key called dateTime which holds dates. What I need to do is add all the entries together for each date and return the array. So I simply got one dateTime per date with all the entries of that day added together. I do not know the dateTime inputs ahead of time as I have a crawler that constantly inserts data into my database.
How would you go about doing that in the most efficient way? I imagine I would have to do a foreach loop and somehow check if the key value (dateTime) changes from the previous key value. And then create a brand new array that I return
An example of the array is as follows:
array (size=130)
0 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '225' (length=3)
1 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '218' (length=3)
2 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '217' (length=3)
3 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '225' (length=3)
4 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '231' (length=3)
5 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '220' (length=3)
6 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '223' (length=3)
7 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '237' (length=3)
8 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '220' (length=3)
So it returns an array like this
array (size=130)
0 =>
array (size=2)
'dateTime' => string '2015-09-01' (length=10)
'entries' => string '660' (length=3)
1 =>
array (size=2)
'dateTime' => string '2015-09-02' (length=10)
'entries' => string '451' (length=3)
2 =>
array (size=2)
'dateTime' => string '2015-09-03' (length=10)
'entries' => string '680' (length=3)
Edit With the help of you guys, I ended up doing the following to get the right format.
function prepareArrayForGraphDates($array){
$results = [];
$finalResult = [];
foreach ($array as $value) {
if (!isset($results[$value['dateTime']])) {
$results[$value['dateTime']] = 0;
}
$results[$value['dateTime']] += $value['entries'];
}
$keyNames = array_keys($results);
for ($x = 0; $x < sizeof($results); $x++) {
$finalResult[$x]['dateTime'] = $keyNames[$x];
$finalResult[$x]['entries'] = $results[$keyNames[$x]];
}
return $finalResult;
}
Use the fact that array keys are unique...
$results = [];
foreach ($array as $value) {
if (!isset($results[$value['dateTime']])) {
$results[$value['dateTime']] = 0;
}
$results[$value['dateTime']] += $value['entries'];
}
You can use an array like a set or a dictionary, using the date as the key.
$data = [
[
'datetime'=>'2015-09-02',
'entries' => 220
]
// ... other entries snipped ...
];
$results = [];
foreach ($data as $date => $entry)
{
// if the date has already been recorded with an initial value, add to it
if (array_key_exists($date, $results) {
$results[$date] += $entry
} else {
// the date is new; add it to the results and set its initial value
$results[$date] = $entry;
}
}

Give filter_var() filter by passing a variable PHP (filter_var() expects parameter 2 to be long, string given)

Right now i'm trying to validate some postdata with filter_var(). I want to get the filter related to each input from my database. So if the input should be filtered by EMAIL, the variable would contain FILTER_VALIDATE_EMAIL. This would then be passed like so:
foreach($this->postdata as $key => $input){
if(!((empty($requirements[$key][1])) || $requirements == 'allowed')){
if(filter_var($input, $requirements[$key][1]) === false){
$errors = true;
}
}
}
The $postdata looks like this:
array (size=4)
'personer_navn' =>
array (size=1)
0 => int 0
'personer_alder' =>
array (size=1)
0 => int 1
'personer_kon' =>
array (size=2)
0 => int 2
1 => int 3
'personer_by' =>
array (size=1)
0 => int 4
And the $requirements looks like this:
array (size=4)
'personer_navn' =>
array (size=4)
0 => string 'string' (length=6)
1 => string 'FILTER_VALIDATE_EMAIL' (length=21)
2 => string '' (length=0)
3 => string '' (length=0)
'personer_alder' =>
array (size=4)
0 => string 'int' (length=3)
1 => string 'FILTER_VALIDATE_EMAIL' (length=21)
2 => string '' (length=0)
3 => string '' (length=0)
'personer_kon' =>
array (size=4)
0 => string 'allowed' (length=7)
1 => string 'allowed' (length=7)
2 => string 'allowed' (length=7)
3 => string 'allowed' (length=7)
'personer_by' =>
array (size=4)
0 => string 'string' (length=6)
1 => string 'FILTER_VALIDATE_EMAIL' (length=21)
2 => string '' (length=0)
3 => string '' (length=0)
Again the problem seems to ba passing $requirements[$key][1] to the filter_var() function.
Any help is appreciated.
FILTER_VALIDATE_EMAIL is not to be used as a string. Try using it without the quotes. Examples can be found in the documentation
A simple change that will fix the bug
foreach($this->postdata as $key => $input){
if(!((empty($requirements[$key][1])) || $requirements == 'allowed')){
if(filter_var($input, constant( $requirements[$key][1]) ) === false){
$errors = true;
}
}
}
The constant function returns the (integer) value of the filter that is string.
read P.P-s answer too.

Find arrays that share a common value from collection of arrays. May be 0 or more matches

I have the following data structure:
array (size=3)
0 =>
array (size=4)
0 => string 'apple' (length=5)
1 => string 'colophon' (length=8)
2 => string 'byo-fusion-drive' (length=16)
3 => string 'scroll-targeting' (length=16)
1 =>
array (size=3)
0 => string 'apply' (length=5)
1 => string 'exploring-web-typography' (length=24)
2 => string 'on-performance-content-management' (length=33)
2 =>
array (size=3)
0 => string 'macbook' (length=7)
1 => string 'colophon' (length=8)
2 => string 'nifty-minidrive' (length=15)
I'm trying to find out which, if any, arrays in my collection of arrays share a common value.
E.g: Arrays 0 and 2 share the string "colophon".
I've tried using array_intersect but this, of course, returns NULL since array 1 has no values in common with the others.
Also, it's possible (likely even) that in any given collection there will be no common value. The collection of arrays will always contain at least two arrays. There could be any number of additional arrays in the collection.
With the data described above, the end result should be something like this:
array (size=2)
0 =>
array (size=4)
0 => string 'apple' (length=5)
1 => string 'colophon' (length=8)
2 => string 'byo-fusion-drive' (length=16)
3 => string 'scroll-targeting' (length=16)
1 =>
array (size=3)
0 => string 'macbook' (length=7)
1 => string 'colophon' (length=8)
2 => string 'nifty-minidrive' (length=15)
I.e: With array 1 (from the original) being removed as it shares no common value.
I'm sure there's a simple way to do this, but I have been trying for 8+ hours now and have decided to ask for help.
Anyone?
You'll need to iterate it with a nested loop. like so:
$array = array(
array(
"apple",
"colophon",
"byo-fusion-drive",
"scroll-targeting"
),
array(
"apply",
"exploring-web-typography",
"on-performance-content-management"
),
array(
"macbook",
"colophon",
"nifty-minidrive"
)
);
for ($i = 0; $i < count($array); $i++) {
for ($j = $i+1; $j < count($array); $j++) {
var_dump(array_intersect($array[$i], $array[$j]));
}
}
Which outputs:
array (size=0)
empty
array (size=1)
1 => string 'colophon' (length=8)
array (size=0)
empty
A simple modification to the loop gives the expected behavior:
$result = array();
for ($i = 0; $i < count($array); $i++) { //Start from the first array, and continue up to all of them.
for ($j = $i+1; $j < count($array); $j++) { //Start with the current array of $i, +1. So that collisions never occur.
if (count(array_intersect($array[$i], $array[$j])) !== 0) { //If there are common values (the array_intersect() function returns a non-empty array
if (!in_array($array[$i], $result)) $result[] = $array[$i]; //Add the first array (if it's not there already)
if (!in_array($array[$j], $result)) $result[] = $array[$j]; //Add the second array (if it's not there already)
}
}
}
Which outputs
array (size=2)
0 =>
array (size=4)
0 => string 'apple' (length=5)
1 => string 'colophon' (length=8)
2 => string 'byo-fusion-drive' (length=16)
3 => string 'scroll-targeting' (length=16)
1 =>
array (size=3)
0 => string 'macbook' (length=7)
1 => string 'colophon' (length=8)
2 => string 'nifty-minidrive' (length=15)
Try
$arr = array (
array('apple', 'colophon', 'byo-fusion-drive', 'scroll-targeting', ),
array('apply', 'exploring-web-typography', 'on-performance-content-management', ),
array('macbook', 'colophon', 'nifty-minidrive', 'nifty-minidrive', ),
);
$repeated_values = array_keys(
array_filter(
array_count_values(
array_reduce($arr, function ($res, $value) {
return array_merge($res, array_unique($value));
}, array()
)
), function ($count) {
return $count > 1;
})
);
$result = array_filter($arr, function($value) use ($repeated_values) {
if (sizeof(array_intersect($repeated_values, $value)) > 0) return true;
});
var_dump($result);
Output
array (size=2)
0 =>
array (size=4)
0 => string 'apple' (length=5)
1 => string 'colophon' (length=8)
2 => string 'byo-fusion-drive' (length=16)
3 => string 'scroll-targeting' (length=16)
2 =>
array (size=4)
0 => string 'macbook' (length=7)
1 => string 'colophon' (length=8)
2 => string 'nifty-minidrive' (length=15)
3 => string 'nifty-minidrive' (length=15)

Categories