Perform "javascript/jQuery-like" functions using PHP - javascript

I'm trying to move some processing from client to server side.
I am doing this via AJAX.
In this case t is a URL like this: https://itunes.apple.com/us/podcast/real-crime-profile/id1081244497?mt=2&uo=2.
First problem, I need to send a bunch of these URLs through this little function, to just pull out "1081244497" using my example. The following accomplishes this in javascript, but not sure how to make it loop in PHP.
var e = t.match(/id(\d+)/);
if (e) {
podcastid= e[1];
} else {
podcastid = t.match(/\d+/);
}
The next part is trickier. I can pass one of these podcastid at a time into AJAX and get back what I need, like so:
$.ajax({
url: 'https://itunes.apple.com/lookup',
data: {
id: podcastid,
entity: 'podcast'
},
type: 'GET',
dataType: 'jsonp',
timeout: 5000,
success: function(data) {
console.log(data.results);
},
});
What I don't know how to do is accomplish this same thing in PHP, but also using the list of podcastids without passing one at a time (but that might be the only way).
Thoughts on how to get started here?
MAJOR EDIT
Okay...let me clarify what I need now given some of the comments.
I have this in PHP:
$sxml = simplexml_load_file($url);
$jObj = json_decode($json);
$new = new stdClass(); // create a new object
foreach( $sxml->entry as $entry ) {
$t = new stdClass();
$t->id = $entry->id;
$new->entries[] = $t; // create an array of objects
}
$newJsonString = json_encode($new);
var_dump($new);
This gives me:
object(stdClass)#27 (1) {
["entries"]=>
array(2) {
[0]=>
object(stdClass)#31 (1) {
["id"]=>
object(SimpleXMLElement)#32 (1) {
[0]=>
string(64) "https://itunes.apple.com/us/podcast/serial/id917918570?mt=2&uo=2"
}
}
[1]=>
object(stdClass)#30 (1) {
["id"]=>
object(SimpleXMLElement)#34 (1) {
[0]=>
string(77) "https://itunes.apple.com/us/podcast/real-crime-profile/id1081244497?mt=2&uo=2"
}
}
}
}
What I need now is to pull out each of the strings (the URLs) and then run them through a function like the following to just end up with this: "917918570,1081244497", which is just a piece of the URL, joined by a commas.
I have this function to get the id number for one at a time, but struggling with how the foreach would work (plus I know there has to be a better way to do this function):
$t="https://itunes.apple.com/us/podcast/real-crime-profile/id1081244497?mt=2&uo=2";
$some =(parse_url($t));
$newsome = ($some['path']);
$bomb = explode("/", $newsome);
$newb = ($bomb[4]);
$mrbill = (str_replace("id","",$newb,$i));
print_r($mrbill);
//outputs 1081244497

find match preg_match() and http_build_query() to turn array into query string. And file_get_contents() for the request of the data. and json_decode() to parse the json responce into php array.
in the end it should look like this.
$json_array = json_decode(file_get_contents('https://itunes.apple.com/lookup?'.http_build_query(['id'=>25,'entity'=>'podcast'])));
if(preg_match("/id(\d+)/", $string,$matches)){
$matches[0];
}
You may have to mess with this a little. This should get you on the right track though. If you have problems you can always use print_r() or var_dump() to debug.
As far as the Apple API use , to seperate ids
https://itunes.apple.com/lookup?id=909253,284910350
you will get multiple results that come back into an array and you can use a foreach() loop to parse them out.
EDIT
Here is a full example that gets the artist name from a list of urls
$urls = [
'https://itunes.apple.com/us/podcast/real-crime-profile/id1081244497?mt=2&uo=2.',
'https://itunes.apple.com/us/podcast/dan-carlins-hardcore-history/id173001861?mt=2'
];
$podcast_ids = [];
$info = [];
foreach ($urls as $string) {
if (preg_match('/id(\d+)/', $string, $match)) {
$podcast_ids[] = $match[1];
}
}
$json_array = json_decode(file_get_contents('https://itunes.apple.com/lookup?' . http_build_query(['id' => implode(',', $podcast_ids)])));
foreach ($json_array->results as $item) {
$info[] = $item->artistName;
}
print '<pre>';
print_r($info);
print '</pre>';
EDIT 2
To put your object into an array just run it through this
foreach ($sxml->entries as $entry) {
$urls[] = $entry->id[0];
}
When you access and object you use -> when you access an array you use []. Json and xml will parse out in to a combination of both objects and arrays. So you just need to follow the object's path and put the right keys in the right places to unlock that gate.

Related

Extra slash comes in json array

I works on nestable drag and drop. When I drag and drop tiles It generate an array in textarea which is [{},{"id":267},{"id":266}]. Now When I post this array in action page then It posted [{},{\"id\":267},{\"id\":266}]. Why this extra slash comes in array. In action page I convert this array using json_decode. Now How I remove this slash from array or how I ignore this array that I successfully decode this array through jsondecode.
$(document).ready(function()
{
var updateOutput = function(e)
{
var list = e.length ? e : $(e.target),
output = list.data('output');
if (window.JSON) {
output.val(window.JSON.stringify(list.nestable('serialize')));//, null, 2));
} else {
output.val('JSON browser support required for this demo.');
}
};
// activate Nestable for list 1
$('#rightservices').nestable({
group: 1
})
.on('change', updateOutput);
// output initial serialised data
updateOutput($('#rightservices').data('output', $('#siteservices')));
//$('#nestable3').nestable();
});
Sounds like Magic Quotes is set on the server. This is an old, deprecated, feature of PHP where any request data would be automatically escaped with slashes regardless of what is was. You can follow the instructions listed here to disable them. From that page, any of these should work, depending on what you have access to:
In php.ini
This is the most efficient option, if you have access to php.ini.
; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off
In .htaccess
If you don't have access to php.ini:
php_flag magic_quotes_gpc Off
At runtime
This is inefficient, only use if you can't use the above settings.
<?php
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
?>
The below will remove the first object in the array but doesn't really solve the real issue of why it is being added in the first place?
var arr = [{},{\"id\":267},{\"id\":266}];
arr.splice(0,1);

Properly returning a JSON object with an embedded JS function

Updated Post
I have a solution for that problem which works with me so far (only tested on Firefox).
My main goal was to dynamically update a Flot graph with Ajax. I also need to dynamically update the axis styles and you can do this by the tickFormatter option. To avoid the problems I previously had, I simply insert the desired return string in the PHP array and JSON encode that array. After returned to the Ajax function I create a new function using the javascript Function() constructor (Link). I hope this helps someone.
Ajax
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json'
})
.success(function(data) {
var datas = data[0]; // fetch data array
var options = data[1]; // fetch options array
var xReturn = options.xaxes[0].tickFormatter; // fetch return string
var yReturn = options.yaxes[0].tickFormatter;
var xFunc = new Function("val", "axis", xReturn); // create function
var yFunc = new Function("val", "axis", yReturn);
options.xaxes[0].tickFormatter = xFunc; // update tickFormatter with function
options.yaxes[0].tickFormatter = yFunc;
$.plot($("#yw0"), datas, options);
})
.error(function(data) {
$("#error").html(data.responseText); // show error in separate div
});
PHP array
$options = array(
'legend' => array(
'position' => 'nw',
'show' => true,
'margin' => 10,
'backgroundOpacity' => 0.5
),
'grid' => array(
'clickable' => true,
'hoverable' => true
),
'pan' => array('interactive' => true),
'zoom' => array('interactive' => true),
'axisLabels' => array('show' => true),
'xaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"' // enter whatever return value you need
)
),
'yaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"'
)
)
);
I skip the data array as it looks similar. Both arrays get combined and JSON encoded.
public function actionSomeControllerWhichCreatesJSONdata() {
$returnArray = array($data, $options);
echo json_encode($returnArray);
return true;
}
The resulting array looks like the one I've posted in the bottom of this post.
Original Post
I'm trying for hours now, but I can't get this to work.
I have an Ajax request which gets a JSON object as return value on success. This works fine as long as I don't use a JS function in my JSON array. So my JSON array looks as follows (after json_encode):
[{
"data": [{
{1,2},
{3,4},
}],
"function": "function(){return \"foo bar\";}"
}]
In order to get rid of the "'s in the function string. I use str_replace and replace the quoted string with an unquoted one. This then looks like so:
[{
"data": [{
{1,2},
{3,4},
}],
"function": function(){return "foo bar";}
}]
The plain json_encode works fine and my Ajax function reads it as a JSON object. After I replace the string it turns out that the return value is no longer a JSON object but a plain text string. I've tried to parse the string again with jquery.parseJSON() but this results in the syntax error:
SyntaxError: JSON.parse: unexpected keyword at line 1 column 396 of the JSON data
Ajax function:
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json' // or text when trying to parse
})
.success(function(data) {
console.log(data);
var dat = jQuery.parseJSON(data); // trying to parse (only when dataType: "text")
var datas = dat[0]; // or data[0] when datType = json
var options = dat[1]; // ---
$.plot($("#yw0"), datas, options); // trying to update a FLOT window
})
.error(function(data) {
console.log("error");
$("#error").html(data.responseText); // show error in separate div
});
So when using this function and setting the return type to "json", it produces an error. If the return type is "text" and I try to parse the string I get the error above. Is there any solution for this problem or am I doing something completely wrong?
Thank's for your help!
UPDATE
Sorry of course my JSON data is not valid! As I said, my JSON object gets created by json_encode which I guess should get the syntax right. The plain array after son_encode looks like:
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid": {
"clickable":true,
"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel": {
"unit":"Jy",
"id":null,
"name":null},
"tickFormatter":"$tickFormatter$",
"position":"right"
}]
and after str_replace I get
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid":{"clickable":true,"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel":{"unit":"Jy","id":null,"name":null},
"tickFormatter":function(val, axis){return val.toExponential(2)},
"position":"right"
}]
Adeno pointed it out already, your JSON syntax is not valid.
Please try to validate your JSON with a linter, like http://jsonformatter.curiousconcept.com/
This is a bit better:
[{"data":[["1","2"],["3","4"]],"function":"function(){return \"foo bar\";}"}]
And the other thing is: you should not manually deserialize the JSON. All newer versions of jQuery will automatically deserialize JSON based on the response's content-type header.
You already set dataType to json for the ajax request.
The response is JSON and will be de-serialized.
So you can directly use
.success: function(response) {
console.log(response.data);
console.log(response.function);
}
Answer for the questions/issue from the comments:
Now you created invalid JSON again, because "tickFormatter" : function(val, axis){return val.toExponential(2)}, misses the quotes around the function string.
Before you insert the string with str_replace(), you need to take care of escaping and quoting.
You may need a little helper function, which properly escapes a string - to be valid JSON.
you need to use str_replace() correctly: not replacing the outer quotes, just the inner $tickFormatter$.
Wait.. i will provide an example:
// we already have an array, which is JSON encoded
// now you want to insert additional JSON content.
// therefore we use a token replace approach.
// valid JSON - with $token$
$json = '[{"data":[["1","2"],["3","4"]],"tickFormatter":"$tickFormatter$"}]';
// the (future) javascript function is a string.
// it's not properly escaped or quoted to be JSON
// this allows for copy and pasting JS into PHP
$unescaped_functionString = 'function(){return "foo bar";}';
// in order escapre properly, we need a json escaping helper
/**
* #param $value
* #return mixed
*/
function escapeJsonString($value) { # list from www.json.org: (\b backspace, \f formfeed)
$escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
$replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
$result = str_replace($escapers, $replacements, $value);
return $result;
}
// then we escape the function string
$functionString = escapeJsonString($unescaped_functionString);
// now its ready to be inserted into the existing JSON,
// where token $tickFormatter$ is defined
// the token must be in single quotes. you replace just the $token$ and not "$token$".
$json = str_replace('$tickFormatter$', $functionString, $json);
echo $json;
// The result is valid JSON again:
// [{"data":[["1","2"],["3","4"]],"tickFormatter":"function(){return \"foo bar\";}"}]
Next step:
The ajax request is made, the json data is transferred to the client and you want to execute the function you passed in.
So the new question is "How to call/exec a JavaScript function from a string - without using eval?"
In general tunneling is a bad practice, see: Is it valid to define functions in JSON results?
Anyway, there a different ways to do this:
Referencing: http://everythingfrontend.com/posts/studying-javascript-eval.html
eval() - evil, but works.
setTimeout()
setTimeout(" function ", 0);
new Function()
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
document.write
document.write('<script> JS </script>')
data URI
var s = document.createElement('script');
s.src = 'data:text/javascript,' + encodeURIComponent('alert("lorem ipsum")')
document.body.appendChild(s);
JSON cannot contain functions like this.
You can however use Javascript to inject the function into the DOM, so what you want to do is skip the str_replace part and simply create a <script type="text/javascript"></script> element in the DOM and insert the data.function property into there.

HighCharts, Json Format

So i'm attempting to use highcharts with the pie chart drilldown option.
Working with static data this is working perfectly. However, as I would like to use the Pie chart as a form of reporting, Ideally It needs to run with dynamic data.
The top level data is made up of requests. Each request is made up of subsequent tasks.
This is the php I have which retrieves the tasks and requests.
foreach($getRequests as $key=> $val){
$timeArr = explode(':', $val['duration']);
$decTime = ($timeArr[0]) + ($timeArr[1]/60); // this is purely to convert hh:mm to decimal time
$pieData['name'] = $val['name'];
$pieData['y'] = $decTime;
$pieData['drilldown'] = $key;
$pie[]=$pieData;
// This creates the first level of data which the $pie[] array gives the correct format, so when json_encode is applied, the data is usable
$getTasks = $task->getReportTasks($user, $status, $key, $dateRange, $date);
foreach($getTasks as $taskKey => $taskVal){
$pieTasks['id']=$key;
$pieTasks['name'] = "Tasks";
$timeArrTask = explode(':', $taskVal['duration']);
$decTimeTask = ($timeArrTask[0]) + ($timeArrTask[1]/60);
$pieTasks['data'] = array($taskVal['name'], $decTimeTask);
$pie2[] = $pieTasks;
}
}
However by applying the same logic to tasks and using json_encode, I end up with the following.
[
{"id":25684
,"name":"Tasks"
,"data":["test task1",3]
}
,{"id":25684
,"name":"Tasks"
,"data":["testtask2",14.383333333333]
}
,{"id":25689
,"name":"Tasks"
,"data":["testtask3",1]}
]
But the format I need is for tasks with the same request ID, the "id" field to be contained within the same data field.
Like so
[
{"id":25684
,"name":"Tasks"
,"data":[
["test task1",3]
,["testtask2",14.383333333333]
]
}
,{"id":25689
,"name":"Tasks"
,"data":[
["testtask3",1]
]
}
]
where because testtask2 has the same id, it is contained within the same data field.
I hope this makes sense and any help anyone can provide so I can structure this correctly would be greatly appreciated.
Not tested, but try to replace the last foreach with this code:
$pieTasks['id'] = $key;
$pieTasks['name'] = "Tasks";
$pieTasks['data'] = array();
foreach($getTasks as $taskKey => $taskVal){
$timeArrTask = explode(':', $taskVal['duration']);
$decTimeTask = ($timeArrTask[0]) + ($timeArrTask[1]/60);
$pieTasks['data'][] = array($taskVal['name'], $decTimeTask);
}
$pie2[] = $pieTasks;
Standart JSON parser can't parse double (14.383333333333) .
Try write in double quotes ( "14.383333333333" )

How could I JSON.parse nested object inside array

I'm trying to pass this structure on a PHP/Ajax response:
{"asn":"167", "jte":"[[1381547700000,0.0], [1381548600000,0.0]]", "visitas":"[{x:1380596400000,text:'HELLO WORLD.',title:'X'}]"}
But JSON.parse returns an error.
SyntaxError: JSON.parse: expected property name or '}'
Without the "visitas" object everything runs fine. Is it possible to "nest" as this?
UPDATE:
Ajax Part:
$.ajax({
type: 'post',
url: 'cxxx.php',
data: { asn: asn },
success: function(p){
p = JSON.parse(p);
jusante=JSON.parse(p.jusante);
montante=JSON.parse(p.montante);
vazao=JSON.parse(p.vazao);
minima=JSON.parse(p.minima);
fator=JSON.parse(p.fator);
visitas=JSON.parse(p.visitas)
and PHP part:
$v="[";
while(odbc_fetch_row($res)){
$datavisita = odbc_result($res, "DATA_VISITA");
$descricaovisita = odbc_result($res, "DESCRICAO_VISITA");
$login = odbc_result($res, "LOGIN");
$descricaomotivo = odbc_result($res, "DESCRICAO_MOTIVO");
$id_motivo=odbc_result($res, "ID_MOTIVO");
$datavisita=date("U", strtotime($datavisita))*1000;
$descricaovisita=preg_replace("/\r|\n/", "", $descricaovisita);
$v.="{x:$datavisita,text:'$descricaovisita',title:'$id_motivo'}, ";
}
$v=rtrim($v,", ")."]";
echo "{\"asn\": \"$asn\", \"description\": \"$description\", \"jusante\": \"$o\", \"montante\": \"$m\", \"vazao\": \"$f\", \"minima\": \"$mn\", \"fator\": \"$fp\", \"visitas\": \"$v\" }";
the Json you are using is valid, I checked it on JSONLint, so your problem might be with serialization, just make sure your "visitas" object is serialized correctly because the problem might be happening because it's the only member with an object value inside
Remove the quotes around the visitas array:
var json = JSON.parse('{"asn": "167","jte": "[[1381547700000,0.0], [1381548600000,0.0]]", "visitas": [{"x": "1380596400000", "text":"HELLOWORLD.","title":"X"}]}');
While the outermost JSON object looks fine, there might be a problem with the nested one!
If you are trying to parse the nested JSON element "visitas" you might have a problem in the fact that your property names (e.g. x, text and title) are not enclosed in quotation marks ("). This is of course a bit tricky since you are trying to include the visitas element as a string.
A solution might be to include the visitas element as a proper JSON element instead.
You need to escape the single quotes. I imagine you are surrounding the above in single quotes when you pass it to JSON.parse.
The below works.
JSON.parse('{"asn":"167", "jte":"[[1381547700000,0.0], [1381548600000,0.0]]", "visitas":"[{x:1380596400000,text:\'HELLO WORLD.\',title:\'X\'}]"}');
Note the slashes before the single quotes inside the string.
I would do the following:
var jsondata = {
"asn": "167",
"jte": "[[1381547700000,0.0], [1381548600000,0.0]]",
"visitas": "[{x:1380596400000,text:'HELLO WORLD.',title:'X'}]"
};
jsondata = JSON.stringify(jsondata);
then send it to php
var postdata = { data : jsondata};
var url = "<?php echo base_url(); ?>"+"test";
$.post(url, postdata, function(result){
console.log(result);
});
sice your php result is echoed the wrong way you should fix that first. Create arrays so that you can easily use the JSON_ENCODE function like so:
$array = array(
"asn" => "test_asn",
"description" => "description_test",
"jusante" => "jusante_test",
"montante" => "montante_test",
"vazao" => "vazao_test",
"minima" => "minima_test",
"fator" => "fator_test",
"visitas" => "visitas_test"
);
$json = json_encode($array);
echo $json;

json_encode with multidimensional array returning string "array" instead of data

I am passing a multidimensional array back to a .php file using json, jquery, and ajax. My goal is essentially to fill a drop down box (id=project) with multiple entries. Here's some code snippets:
$("#turninId").change(function() {
var user_id = $("#turninId").val();
$.ajax ( {
url:"send_input.php",
type: "POST",
dataType: "json",
data:{id_selection: user_id},
success:function(response) {
for (var i=0; i<response.proj.length; i++) {
$("#exp").html(response.proj[i]);
$("#project").html(response.proj[i]); } });
});
In send_input.php (backend), I query a db, and send the information to an array. Then I use json_encode.
$query="SELECT project FROM main";
$results = $db->query($query);
while ($row_id = $results->fetchArray()) {
$proj_option[] = "<option value=\"".$row_id['project']."\">".$row_id['project']."</option>\n";
$pselected=$row_id['project'];
}
$output = array( "proj" => "$proj_option");
echo json_encode($output);
My problem is that this is RETURNING THE STRING "Array".
For example, if I do: response.proj[0], I get "A" returned.
What gives? I've seen a few people with questions about this error, but no definite solution. Any help?
This is because you are casting $proj_option to a string by enclosing it in quotes. Just remove the quotes and you will get the array.

Categories

Resources