In my local environment I'm using the PHP7 and I developed a Restful API to an AngularJS application. I need do a get request to the Api and pass an array as parameter, so I did it:
$http.get("/Api/MyUrl.php", {
params: {
"Names[]": ["Foo", "Bar"]
}
})
.then(function(response){ //fires in success
console.log(response.data);
}, function(response){ //fires in error
console.log(response.statusText);
});
In MyUrl.php file I printed the parameters in the screen like this:
<?php
print_r($_GET);
?>
When it was executed, exactly what I imagined was printed on the browser console:
Array
(
[Names] => Array
(
[0] => Foo
[1] => Bar
)
)
Until here there's no problem. But, when I uploaded the application in the server, that supports only the 5.6 PHP version (I don't know if it's correlated, but I think so), the parameter with the array is gotten by the PHP in another way, and what is printed on console is that:
Array
(
[Names%5B%5D] => Bar
)
It "undestands" the [] signals as its HTML codes (%5B and %5D), get only the last element of the array and interprets as a commom variable.
What I need to do to read the parameters in the server in the same way that I do in the local environment?
Good question. I suggest you checkout this old issue in angularjs project where it reads:
There is no particular standard for how arrays should be serialized into query strings. Different back ends expect different formats. This current method (in 1.1.x) was chosen specifically because it allows the developer the most flexibility.
The way you are passing params to $http.get() seems to work for php7.0 because php7.0 may be smart enough to infer that brackets are being passed. But the fact is that the query string in your angular code is not properly URI-encoded so it fails against your server.
Interestingly, a similar issue has been reported here the answer to which references documentation from jQuery which has the same behavior:
Because there is no universally agreed-upon specification for param strings, it is not possible to encode complex data structures using this method in a manner that works ideally across all languages supporting such input. Use JSON format as an alternative for encoding complex data instead.
What is the solution?
For a start, you can try URI-encoding your params.
Another solution would be to pass your query as json encoded data:
$http.get("/Api/MyUrl.php", {
params: {
"data": JSON.stringify({'names': {'Foo', 'Bar'}})
}
})
and json_decode($_GET['data']) to access your parameters in backend.
And lastly, you can take advantage of AngularJS's paramSerializer to define your own serializer and pass your params as you used to.
In this particular case, paramSerializerJQLike will be useful:
$http.get("/Api/MyUrl.php", {
params: {
"Names[]": ["Foo", "Bar"]
}
paramSerializer: '$httpParamSerializerJQLike'
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
Related
In the existing SO literature, I have seen examples that use jquery and PHP to proxy data:
jquery
function loadTheUrl(x){
$.ajax({ url: 'loader.php',
data: {url: x},
type: 'get',
success: function(output) {
$('.loading-space').html(output);
}
});
}
PHP
<?php
$doc = new DOMDocument();
$doc->loadHTML(file_get_contents($_GET['https://www.google.com/finance/getprices?q=.NSEI&x=NSE&i=600&p=1d&f=d,o']));
echo $doc->saveHTML();
Here is what the first few lines of the data look like at the URL seen in the PHP above. It is a page of plain text only, like this:
MARKET_OPEN_MINUTE=570
MARKET_CLOSE_MINUTE=960
INTERVAL=300
COLUMNS=DATE,OPEN
DATA=
TIMEZONE_OFFSET=-240
a1521120900,555.45
1,554.53
2,554.07
3,553.9
4,552.67
...
As far as I know, the PHP is correct. For my use case, I need to replicate the above jquery by means of d3. I was hoping that d3 would have something to use to interface with the data my php file is spitting out.
If you are wondering why I am going to such lengths, it's because my browsers are not letting me run scripts (i.e. d3.text(), d3.csv() et all) directly by say d3.text('https://www.google.com/finance...') due to the infamous access control origin header error. So my plan is to mirror the data from the google backfill off a local php file that I'm serving from my server. This way everybody is happy (or at least me).
When I try calling d3.text() on my php file, my data was not loaded correctly. In other words I tried: d3.text('my_loader.php'). But that resulted in lots of NaN errors, which I usually noticed are symptoms of a parsing error of some sort. Checking back through my code, things seem fine though. I have unary parsing in place, the strings should be cast to numbers. In fact, everything was working fine offline. I could load and parse the data directly when in my IDE. It was only when I published my d3 graph to the web did I realize I couldn't parse data from different origins. This is the point where I added the PHP component. My hunch was that d3 was actually trying to parse my PHP page and not the URL the PHP was pointing to. I later confirmed this by passing the data returned by d3.text() in the console and it was indeed the PHP page itself.
Question: In light of my cross-origin data situation, what can I do from the d3 side or the PHP side to make the two interface with each other correctly? I wonder if d3 is only suited for same origin data, or if there actually is a method to read/parse cross-origin data using a technique I'm not aware of (PHP or otherwise).
The url you are fetching does not exist within the $_GET variable.
The parameters you are submitting are an array:
$_GET = ['url' => 'some_url'];
Which means this:
$_GET['https://www.google.com/finance/getprices?q=.NSEI&x=NSE&i=600&p=1d&f=d,o]
is wrong (it's also missing a quote mark at the end of the string).
It should be $_GET['url']
With no validation:
<?php
header('Content-Type: text/plain');
echo file_get_contents($_GET['url']);
But that's neither here nor there.
The issue, I think, is with the url being passed. It contains a question mark and multiple ampersands (? and &). I think this is bjorking up the $_GET parameter so all you're getting is https://www.google.com/finance/getprices?q=.NSEI. You need to wrap the url in encodeURIComponent:
var url = encodeURIComponent('https://www.google.com/finance/getprices?q=.NSEI&x=NSE&i=600&p=1d&f=d,o');
d3.text('/path/to/myscript.php?url=' + url);
Cross origin applies to all ajax requests, instead of requesting d3.text('https://www.google.com/finance...') why not try d3.text('mymethod.php') and make sure the method returns a text file rather than html via the headers:
<?php
header('Content-Type: text/plain');
$file = file_get_contents('https://www.google.com/finance/getprices?q=.NSEI&x=NSE&i=600&p=1d&f=d,o');
echo $file;
I am using Yii2, and for what it's worth, I know the basics, and have been programming for a while. This is probably from a lack of documentation in this area (Yii2 JSONP and Responses). All I find is examples of returning a JSON response, none showing a JSONP response.
I started here, the Yii Cookbook:
https://github.com/samdark/yii2-cookbook/blob/master/book/response-formats.md
It only shows examples of JSON and XML, but not JSONP. It states to use FORMAT_JSONP. So I swapped the JSON example with JSONP. Go to the URL, nothing, just a blank white page. So I var_dump() the data, and yes the data is there!
So after searching Google for "yii2 jsonp", "yii2 jsonp error", "yii2 jsonp doesn't work", along with a few other variations, I found nothing.. I searched here on SO, and only 2 questions show up for "yii2 jsonp", neither were of any help.
I proceeded to the Yii2 docs.
Here: http://www.yiiframework.com/doc-2.0/guide-runtime-responses.html
Again, no JSONP example and not much talk about it other than FORMAT_JSONP is a valid format type...
I can use JSON just fine, however I am trying to populate a Google Map with data from a JSONP response, hence why I need JSONP.
Here is my Controller:
public function actionMapapi()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSONP;
$data = User::find()->all();
return $data;
}
When I go to the URL, it's just white. I can place a die('here') before declaring the response->format, and it prints "here" on the page. So the controller is being accessed just fine. If I swap FORMAT_JSONP with FORMAT_JSON it works perfect, it's just not JSONP.
It seems there is a gap on how to exactly handle JSONP in the Yii2 docs, and not much talking about it online (that I could possibly find).
You need to return an array that defines your callback and data. This is fairly hidden, and mentioned here: http://www.yiiframework.com/doc-2.0/yii-web-jsonresponseformatter.html
It states:
$useJsonp Whether to use JSONP response format. When this is true, the response data must be an array consisting of data and callback members. The latter should be a JavaScript function name while the former will be passed to this function as a parameter.
With virtually no examples that I could find, I just tried the obvious:
return ['data' => $arrayData, 'callback' => 'myCallback'];
It Worked!
Full source of my Controller:
public function actionMapapi()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSONP;
$callback = 'mapApiCallback';
$data = User::find()->all();
return ['callback' => $callback, 'data' => $data];
}
NOTE: No, I am not populating my map with the users. It's just an example, and the data prints on the screen just fine. I still have to code it to pull my map data to pass to my Google map.
If anyone is interested, I am using: 2Amigos: Yii2 Google Maps Library
I don't know if it currently supports populating a map with JSONP data, but I will probably extend it if I have to.
Assume I have this object in JavaScript which is built like this:
var obj = {};
var fields = ['table_name[field_name]', 'tale_name[field_name_2]']
for(var i; i < fields.length; i++){
obj[fields[i]] = someBulkOfData;
}
when logged in the console, obj will output
{
table_name[field_name] : {...},
tabke_name[field_name_2] : {...}
}
This works all fine, until I pass the object through PHP by jQuery.ajax().
When I receive my request in PHP, the array looks as follow:
[
['table_name[field_name'] => ...,
['table_name[field_name_2'] => ...
]
So what happens here is that somewhere between sending the AJAX-request and receiving the data in PHP, the last square bracket of every key dissappears.
Could someone explain to me why this happens, and if there is a neat way to solve this problem?
I have one criteria for the solution, and that is that I cannot change the keys (as in something like 'table_name\[field_name\]').
have you tried using $.serialize()?
use serialize to turn a javascript object into a string that can be transmitted with AJAX easily - like this:
var ajaxableString = $(obj).serialize();
You could solve that issue by restructuring your JS object:
{
table_name : {
field_name_1 : {...},
field_name_2 : {...}
},
another_table : {
...
}
}
That way you avoid that weird naming convention.
Also, I suspect you are hiding something from us. There is something (an operation) between the this and PHP, maybe somewhere in your AJAX code, that you are not telling us. Maybe you are serializing this object into a string and passing the string as one query parameter to the server. This serialize step might be the cause.
But just to be sure, you can check the Net section of the debugger and check the request headers if the data sent is formatted perfectly.
As far as I know, jQuery.ajax accepts a JS object as data, and perfectly converts it into querystrings. By that, you don't need to serialize it manually.
The solution is, thanks to #fab , to encode the data with JSON:
$.ajax({
data : {
obj:JSON.stringify(obj)
},
...
});
In PHP:
json_decode($_REQUEST['obj']);
This will output a perfectly nice stdClass object, with preserved keys.
i'm working on an php-application, and now i have to build an interface to communicate between jquery and php. i already have a working controller/action. what is the best way to communicate with jQuery, if i need to send an array to php in the request.
example:
data that is needed to fulfill the request:
$request_data = array
(
'key1' => 'value1',
'list1' => array
(
'listkey1' => 'listvalue1',
)
)
should i send this in different as "normal" post-request, or is it easier to send one post-var with the array encoded in json? ($post_json="{key: value....})
the focus is on easy integration in jquery
edit: it is not about passing the data to the client, it is about passing the array from the client to the php-script
use phps json_encode() to generate the response, and read it with jquery on client?
$.getJSON('youpage.php', function(data) {
$.each(data, function(key, value) {
alert(key + '=>' + value);
});
}
http://php.net/manual/en/function.json-encode.php
UPDATE
in regards to communication the other way, from the client to php. It all depends on the task at hand really. If the data in the drop down purely depend on the entries on the form, and they are otherwise stateless. Then,the best route will depends on your backend code, you could do a ajax post, with the individual variables, or concatenate them into one variable before sending, and then splitting them up on the backend. Or, as you say, you could create a json string and then use json_decode on the backend.
Which route is fit for purpose depends on many factors, and I dont think there is a right or wrong error.
Personally, I would generate a AJAX post request (im not a php coder though) to the backend, and then process the request object directly. You still would need to process a data structure, so why add the overhead/extra-step of deserializing json from the request.
You can use jquery post
$.post('url', data, function(data) {
console.log(data);
});
YOu can access the data in php
echo $_POST['key1'];
echo $_POST['key2'];
I have a global variable I'm using to store a bunch of information in a project I'm working on. It is an object with various values and I guess other objects in it. For example...
$.myVar {
currentProj : "Project 1",
allProjs : [],
toggleVar : 0
}
Now as the program runs and I do things, I'm actually adding arrays within allProjs. I want to use the array index as the name of the project, and then it contains a bunch of information. Here is a sample of what the object looks like after running the program for a few minutes.
(copied from Chrome's console):
$.myVar
Object
currentProj: "McB2"
toggleVar: 0
allProjs: Array[0]
McB1: Array[0]
length: 0
__proto__: Array[0]
McB2: Array[4]
0: "02070124"
1: "02030036"
2: "02090313"
3: "02090450"
length: 4
Now I want to pass this data to a PHP file using $.post so I can convert it to JSON and save it on the server.
I do this basically by just running:
$.post('saveJSON.php', $.myVar, function(data) {
$('#dumpspace').html(data);
});
For debugging I've got the PHP file just outputting:
print_r($_REQUEST);
Now I would expect a multi-dimensional array that I could convert to JSON and then save, but all it is spitting out is:
Array ( [currentProj] => McB2 [toggelVar] => 0 )
So I can see that it's not sending the the allProj section of the object, but I'm not sure why! It does seem to show up when I look at the object in the console, so I'm not sure what I'm missing.
Any help is appreciated.
Thanks!
Clarification
The first section, where I declare allProjs, is it possible I'm doing something wrong there? When I run Stringify, I end up with a similarly wrong result:
JSON.stringify($.myVar)
"{"currentProj":"McB2","allProjs":[],"toggleVar":0}"
You need to .stringify the object / array into a JSON string. All "modern" browsers do support this natively with JSON.stringify(obj). If you need to support "older" browser version aswell, you need to go to http://www.json.org and download the json2.js lib which offers the same functionality.
The other way around, if you want to receive a JSONized string from a server, you need to either tell jQuery that you're expecting a json string by passing 'json' into your $.post() call, or you need to parse the received data yourself by again accessing the JSON object. JSON.parse(json_string) will return a Javascript object from a passed in JSON string.
Figured out my problem. When I was declaring the object originally I was making allProj and Array by putting in []. If I put it in as allProj : {}, then it works perfectly! Thanks for the suggestions, helped narrow down my mistake.
-M
I believe you must first convert your array to the JSON format before posting to PHP.
This is the method I have used in the past:
var jsonOb = JSON.stringify(yourArray);
$.post(
"yourPage.php",
{jsonOb:jsonOb},
function(r){
//your success response
}
);
Hope this does the trick brother!
W.