How to `unstring` an object wrapped in a string without calling it? - php

I have an array with values that are objects wrapped as strings, how can I turn them back into objects without calling them? ['randomNumber' => '$this->faker->randomNumber()']
This array is being passed into a stub (writing a php file):
$replace = [
'{{mappedResult}}' => var_export($mappedResults, 1),
];
instead of getting this array:
$mappedResults = ['randomNumber' => $this->faker->randomNumber()]
I get this array instead:
$mappedResults = ['randomNumber' => '$this->faker->randomNumber()']

If you want to use the return value of the method call as the value in the map, you can use eval:
foreach ($mappedResults as $key => $value)
$mappedResults[$key] = eval($value)
Note eval returns NULL unless a return statement is called in the code string. Then the value passed to return is returned. If there is a parse error in the code string, eval() returns FALSE.
Hence you don't want to call and evaluate the code and based on my understanding you want to recreate the php file, you should use a custom export function that can remove quotations:
function export($input) {
$response = [];
foreach($input as $key => $value)
$response[] = var_export($key, true) . " => " . $value;
return "[".implode(",",$response)."]";
}

Related

PHP - How to parse json data and compare it

I hope you all having a great day. I'm developing a simple wordpress plugin and I've never worked with JSON encoded data on PHP before so I need some help here.
I have this simple function with a single parameter that's called in a 'foreach' loop and inside this function I have an array of values pulled from DB and it's JSON encoded, it goes like this:
array (size=4)
0 => string '[{"videoUrl":"https://vimeo.com/493156200","playlistID":"7992"}]' (length=64)
1 => string '[{"videoUrl":"https://vimeo.com/365531165","playlistID":"7992"}]' (length=64)
2 => string '[{"videoUrl":"https://vimeo.com/365531139","playlistID":"7992"}]' (length=64)
3 => string '[{"videoUrl":"https://vimeo.com/521605944","playlistID":"7992"}]' (length=64)
My function goes like this:
$playlist_id = 7992;
function videostatuschecker($x){
$unlockedvideos = ['json encoded data illustrated above'];
// x value is like this: $x = 'https://vimeo.com/493156200';
if (in_array($x, $unlockedvideos)){
return 'unlocked';
}
else{
return 'locked';
}
}
Video URL will be passed through my function's parameter variable and playlist ID is defined in the parent function so it's static.
Now what I need is, I need to compare that $x value to "videoUrl" values in the array and compare its 'playlistID' to $playlist_id variable and if they both match, I need the function to return 'unlocked' and vice versa for the else statement. Any help is much appreciated, thank you so much.
You could do something like this:
function videostatuschecker($video_url, $playlist_id){
$unlockedvideos = [
'[{"videoUrl":"https://vimeo.com/493156200","playlistID":"7992"}]',
'[{"videoUrl":"https://vimeo.com/365531165","playlistID":"7992"}]',
'[{"videoUrl":"https://vimeo.com/365531139","playlistID":"7992"}]',
'[{"videoUrl":"https://vimeo.com/521605944","playlistID":"7992"}]'
];
foreach ($unlockedvideos as $unlockedvideo) {
$decoded = json_decode($unlockedvideo);
if ($playlist_id == $decoded[0]->playlistID && $video_url == $decoded[0]->videoUrl) {
return 'unlocked';
}
}
return 'locked';
}
print(videostatuschecker('https://vimeo.com/493156200', 7992));
Please note that your $unlockedvideos is an array of arrays. Is that what you want?

Convert string to array in API call

I am passing an array as a string in parameter to an api in php like this:
http://xx.xx.xx.xx/api.php?query="array(done = 1)"
In my api file, I have used this array to hit a mongodb query:
$query = $_REQUEST['query'];
$cursor = $collection->find($query);
But this didn't work. When I hard-coded array(done = 1) into the find query, it seems to work fine.
if (array('done' => 1) == $query) {
echo "Y";
}
else {
echo "N";
}
The above code prints N. So I guess it's because $query is being passed as a string.
PS: I also tried json_encode, json_decode and unserialize but it didn't work. I might be doing omething wrong here.
Well make bit change in your query string, you passing in api request.
Suppose belowis your array.
$array = array('done' => 1, 'message' => 'success');
USE array_map_assoc function with some customization, which make easy to implode associative array
function array_map_assoc( $callback , $array ){
$r = array();
foreach ($array as $key=>$value)
$r[$key] = $callback($key,$value);
return $r;
}
Generate your data to be sent in api
our data
$queryString = implode('&',array_map_assoc(function($k,$v){return "$k=$v";},$array));
Now send your data with API
$url = "http://xx.xx.xx.xx/api.php?" . $queryString ;
Now use print_r($_GET) in your API page and you will receive data like below
Array
(
[done] => 1
[message] => success
)
This make your code easy to handle and use in either if condition or sql query.

How to change the array in order to make the desired JSON object in PHP?

I've an array titled $request as follows :
Array
(
[invite_emails] => suka#gmail.com, swat#gmail.com
[page_id] => 322
[ws_url] => http://app.knockknot.com/api/group/sendInvitation
)
After using json_encode($request) I got following output:
{
"invite_emails": "suka#gmail.com, swat#gmail.com",
"page_id": "322",
"ws_url": "http://app.knockknot.com/api/group/sendInvitation"
}
But actually I want the JSON object as follows :
{
"page_id": 322,
"invite_emails": [
"suka#gmail.com",
"swat#gmail.com"
],
"ws_url": "http://app.knockknot.com/api/group/sendInvitation"
}
How should I manipulate the array in PHP in order to get the above desired JSON object?
Please someone help me.
Split the list of emails using the comma:
$array["invite_emails"] = preg_split("#\s*,\s*#", $array["invite_emails"]);
I personally prefer using callback functions for readability and possibilities. To your purpose, array_walk should fit:
<?php
// reproducing array
$request = array(
"invite_emails" => "suka#gmail.com, swat#gmail.com",
"page_id" => 322,
"ws_url" => "http://app.knockknot.com/api/group/sendInvitation"
);
// callback finds a comma-separated string and explodes it...
array_walk($request, function (&$v,$k) {if ($k == 'invite_emails') $v = explode(", ", $v);});
// ... and then encode it to JSON
json_encode($request);
// testing
print_r($request);
OUTPUT:
{
"invite_emails":[
"suka#gmail.com",
"swat#gmail.com"
],
"page_id":322,
"ws_url":"http://app.knockknot.com/api/group/sendInvitation"
}
You are free to change the field if your needs changes, and even suppress it to be used with any field of the array.
Use PHP explode for example:
$array['invite_emails'] = explode(',',$array['invite_emails']);
To avoid spaces use preg_split (source):
$array['invite_emails'] = preg_split("/[\s,]+/", $array['invite_emails']);
This entry:
[invite_emails] => suka#gmail.com, swat#gmail.com
should be an array (currently, it is a string) in PHP, then in JSON it will look like you want it.

PHP: Recursive htmlspecialchars on object

I want to establish a generic sanitizer for my data that comes from various sources. With sanitizing I mean (at this stage) applying htmlspecialchars to strings. Now, the data that comes from these sources can be anything from an object to an array to a string, all nested (and complicated), and the format is always a bit different.
So I thought of a recursive htmlspecialchars function that applies itself to arrays and objects, and only applies htmlspecialchars to strings, but how do I walk an object recursively?
Thanks.
EDIT: I think I should have mentioned this - I am actually building a RIA that relies heavily on JS and JSON for client-server communication. The only thing the server does is fetching stuff from the database and returning it to the client via JSON, in the following format:
{"stat":"ok","data":{...}}
Now as I said, data could be anything, not only coming from a DB in the form of strings, but also coming from an XML
The workflow to process the JSON is as follows:
Fetch data from the DB/XML (source encoding is iso-8859-1)
Put them into the "data" array
Recursively convert from iso-8859-1 to utf-8 using
private function utf8_encode_deep(&$input) {
if (is_string($input)) {
$input = $this -> str_encode_utf8($input);
} else if (is_array($input)) {
foreach ($input as &$value) {
$this -> utf8_encode_deep($value);
}
unset($value);
} else if (is_object($input)) {
$vars = array_keys(get_object_vars($input));
foreach ($vars as $var) {
$this -> utf8_encode_deep($input -> $var);
}
}
}
Use PHP's json_encode to convert the data into JSON
Send (echo) the data to the client
Render the data using JS (e.g. putting into a table)
And somewhere in between that, the data should be somehow sanitized (at this stage only htmlspecialchars). Now the question should have been: Where to sanitize, using what method?
You can try the following
class MyClass {
public $var1 = '<b>value 1</b>';
public $var2 = '<b>value 2</b>';
public $var3 = array('<b>value 3</b>');
}
$list = array();
$list[0]['nice'] = range("A", "C");
$list[0]['bad'] = array("<div>A</div>","<div>B</div>","<div>C</div>",new MyClass());
$list["<b>gloo</b>"] = array(new MyClass(),"<b>WOW</b>");
var_dump(__htmlspecialchars($list));
Function Used
function __htmlspecialchars($data) {
if (is_array($data)) {
foreach ( $data as $key => $value ) {
$data[htmlspecialchars($key)] = __htmlspecialchars($value);
}
} else if (is_object($data)) {
$values = get_class_vars(get_class($data));
foreach ( $values as $key => $value ) {
$data->{htmlspecialchars($key)} = __htmlspecialchars($value);
}
} else {
$data = htmlspecialchars($data);
}
return $data;
}
Output Something like
array
0 =>
array
'nice' =>
array
0 => string 'A' (length=1)
1 => string 'B' (length=1)
2 => string 'C' (length=1)
'bad' =>
array
0 => string '<div>A</div>' (length=24)
1 => string '<div>B</div>' (length=24)
2 => string '<div>C</div>' (length=24)
3 =>
object(MyClass)[1]
...
array
0 =>
object(MyClass)[2]
public 'var1' => string '<b>value 1</b>' (length=26)
public 'var2' => string '<b>value 2</b>' (length=26)
public 'var3' =>
array
...
You would only want to escape when outputting into HTML. And you cannot output a complete array or object into HTML, so escaping everything seems invalid.
You have one level of indirection because of your JSON output. So you cannot decide in PHP what context the data is used for - JSON is still plain text, not HTML.
So to decide whether any data inside the JSON must be escaped for HTML we must know how your Javascript is using the JSON data.
Example: If your JSON is seen as plain text, and contains something like <b>BOLD</b>, then the expected outcome when used inside any HTML is exactly this text, including the chars that look like HTML tags, but no bold typesetting. This will only happen if your Javascript client handles this test as plain text, e.g. it DOES NOT use innerHTML() to place it on the page, because that would activate the HTML tags, but only innerText() or textContent() or any other convenience method in e.g. jQuery (.text()).
If on the other hand you expect the JSON to include readymade HTML that is fed into innerHTML(), then you have to escape this string before it is put into JSON. BUT you must escape the whole string only if you do not want to add any formatting to it. Otherwise you are in a situation that uses templates for mixing predefined formatting with user content: The user content has to be escaped when put into HTML context, but the result must not - otherwise Javascript cannot put it into innerHTML() and enable the formatting.
Basically a global escaping for everything inside your array or object most likely is wrong, unless you know for everything that it will be used in a HTML context by your Javascript.
function htmlrecursive($data){
if (is_array($data) && count($data) > 1){
foreach ($data as &$d){
$d = htmlrecursive($d);
}
} else if (!is_array($data)){
return htmlspecialchars($data);
}
else {
return htmlspecialchars($data[0])
}
}
htmlrecursive($array);
For objects you need to implement The ArrayAccess interface then you can do a array walk recursive
Also check this question Getting an object to work with array_walk_recursive in PHP

How do I remove an Attribute from a JSON String utilizing PHP

I have a JSON result in PHP that looks like the following:
[{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015ay6IAA"},"Id":"a03U00000015ay6IAA","Name":"ManagerID-00003"},
{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015ZfJIAU"},"Id":"a03U00000015ZfJIAU","Name":"ManagerID-00001"},
{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015axwIAA"},"Id":"a03U00000015axwIAA","Name":"ManagerID-00002"}]
I want to eliminate the Attributes (which contains Type and URL) so that the JSON result is flattened. So I'd like it to look more like:
[{"Id":"a03U00000015ay6IAA","Name":"ManagerID-00003"},
{"Id":"a03U00000015ay6IAA","Name":"ManagerID-00003"},
{"Id":"a03U00000015ay6IAA","Name":"ManagerID-00003"}]
What is the best way in PHP to eliminate every instance of attributes?
//assign the orignal string to variable $json
$json = '[{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015ay6IAA"},"Id":"a03U00000015ay6IAA","Name":"ManagerID-00003"},{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015ZfJIAU"},"Id":"a03U00000015ZfJIAU","Name":"ManagerID-00001"},{"attributes":{"type":"Manager__c","url":"/services/data/v23.0/sobjects/Manager__c/a03U00000015axwIAA"},"Id":"a03U00000015axwIAA","Name":"ManagerID-00002"}]';
//decode the string with json_decode();
$decoded = json_decode($json);
//loop over the decoded array and populate array with Id and Name only
foreach($decoded as $d) $newarr[] = array('Id' => $d->Id, 'Name' => $d->Name);
//json encode the resulting array.
$finalJSON = json_encode($newarr);
Using json_decode(), array_map() and json_encode() should be easy enough:
function strip_arguments( $item){
$new_result = array(
'Id' => $item['Id'],
'Name' => $item['Name'],
)
return $new_result;
}
$array = json_decode( $input);
$array = array_map( 'strip_arguments', $array);
$input = json_encode( $array);
You of course may use unset() inside strip_arguments (instead of creating new array) but this will make sure any "new attribute" won't make it trough.
You can use return array(...) instead of declaring variable and chain operations to: json_encode(array_map( 'strip_arguments', json_decode( $input))); too :)
Using PHP's JSON's tools you can convert the JSON string into an array, from here use a simple foreach statement and REGEX to delete array entries.
Once this is done simply convert back into a JSON string using PHP functions and do with it as you please :-)
The functions I am thinking off are - json_decode, json_encode.
Thanks
Andrew

Categories