Extra slash comes in json array - javascript

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);

Related

Save data to JSON File in correct format - PHP

I am currently saving click co-ordinates to a JSON file through the use of the following code:
onmouseup = function(e){
var Clicks = {};
Clicks.state = {
cX: e.clientX,
cY: e.clientY,
}
$.ajax({
type : "GET",
url : "PHP/save_json.php",
data : {
state : JSON.stringify(Clicks.state)
}
});
}
<?php
$myFile = "JSON/clicks.json";
$fh = fopen($myFile, 'a') or die("can't open file");
$stringData = $_GET["state"];
fwrite($fh, $stringData);
fclose($fh)
?>
However with the above code I am saving the coordinates in the following incorrect format:
{"cX":467,"cY":374}{"cX":56,"cY":474}
Can anyone please help me to save the coordinates in a JSON array rather than in seperate JSON entries?
I would like the file to be as follows, were the coordinates are added onto the already existing JSON array within the file:
{
"ID":["1","2"],
"cX":["467","56"],
"cY":["374","474"]
}
What you need to do is:
Open the clicks.json file and read the entire contents.
Turn this into an instance of stdClass by using json_decode. This will give you a PHP object that you can modify using normal PHP functions and syntax.
Use json_decode on the JSON that you receive from your client.
Use array_push to push the new values from the client into the arrays stored in the file (something like array_push($fileJson->cX, $clientJson->cX);)
Use json_encode to encode $fileJson again.
Write it back to the file.
This assumes that the clicks.json file is already correctly formatted JSON with the arrays already created etc.
Given the current arrangement of the key and value bits, it's apparent that some sort of transformation is needed in the JSON data before it is written to the file. Where this transformation is done is definitely a matter of an opinion. However, assuming that you receive following JSON data in PHP:
[{"cX":467,"cY":374},{"cX":56,"cY":474}]
The PHP code can be written as (illustrated with static input):
$myFile = "JSON/clicks.json";
$fh = fopen($myFile, 'a') or die("can't open file");
$stringData = $_GET["state"];
$json_array_source = json_decode($string, true);
$json_array_target = array();
foreach($json_array_source as $key=>$value){
$json_array_target["ID"][] = $key + 1;
foreach($value as $sub_key => $sub_value){
$json_array_target[$sub_key][] = $sub_value;
}
}
$transformed_string = json_encode($json_array_target);
fwrite($fh, $transformed_string);
fclose($fh);
If you were to echo $transformed_string;, you'd see:
{"ID":[1,2],"cX":[467,56],"cY":[374,474]}
Which is what will be written to the file.
You need load data to array, add new data and save back to file.
I think you don't need save numbers in strings.
These code create new file if not exists.
<?php
// test input data
if(isset($_GET['state']['cX']) &&
isset($_GET['state']['cY']) &&
is_numeric($_GET['state']['cX']) &&
is_numeric($_GET['state']['cY']) )
{
// ok
} else {
exit('Bad data format');
}
$myFile = __DIR__ . "/JSON/clicks.json";
// step 1, load data from file to array
$array = file_exists($myFile) ?
json_decode(file_get_contents($myFile), true) :
[];
// step 2, add data to array
$array['ID'][] = isset($array['ID']) ? (count($array['ID']) + 1) : 1;
$array['cX'][] = (int) $state['cX'];
$array['cY'][] = (int) $state['cY'];
// step 3, save array back to file
file_put_contents($myFile, json_encode($array));
Or you can use other file format where will be possible to append file. The easiest format for static structured data could be CSV
Use json_encode to convert your string to an object, then convert it back to a string using json_decode and the JSON_PRETTY_PRINT option.
$stringData = json_decode(json_encode($_GET["state"]), JSON_PRETTY_PRINT);
http://php.net/manual/en/function.json-encode.php

Detect URl pattern

I have data collecting software.
Data: site visits/views.
So i have a lot views data: page url, date, visitor info.
Most of URLs is just different filters or something like. I.e URLs same but it have dynamic parameters.
For example:
site1.com/?search=something
site1.com/?search=some_word
site1.com/?search=hello
site1.com/?search=world
Should be "detected" as site1.com/?search={variable}
So that is a question:
Any algorithms to auto-detect patterns of URL?
Or some analyzing classes/functions? Any programming language.
Need solution that can process big batches of URLs.
Wihout any manual pattern defining(coz i dont know it and cant do it manually for many different sites).
UPD
For example:
I have many different URLs. From many sites. I dont know how these sites work. So i need to get for example 500 URLs from one site then compare and group it by common part to get 10 unique urls as result. Which should be automatically merged via replacing with {var} any dynamic URL parts.
I think you won't get much out of a simple pattern, and have to write partially Complex algorithm something along the line of:
break each URI to it's parts: domain, page, Query-String (as keys-values)
group all URIs from same domain
if there is a page, group by that too. (most sites today use url rewrite rules so there isn't a real "PAGE")
here come the "hard part":
Match Query String Variables between the grouped URIs
if a Var is matching All(almost, all) uris, it might be meaningful to the content.
if all (almost) have the same value, it might be smth less meaningful...
note: you should also pre-check some common VarIds like: search, q,query, id,itemId, etc...
One last thing, today, as i mentioned, parts of the URL (aside from queryString) can infer dynamic parameters (e.g. Ebay items: www.ebay.com/itm/9125483; www.ebay.com/itm/{itemId})
but hey, that's why you are paid for, to think about all those issues :p
Good luck.
Here is some kind Proof of Concept :)
Example of splitting URL by "?"
Parse parameters.
Calculate frequency for unique parameter values.
Get Nth percentile.
Build URLs and replace parameters which frequency is more than Nth percentile
For small data like here in sandbox 50 percentile is enough to group some URL.
For "big real data" 90-95 percentile.
For example: I use 90 percentile for 5000 links -> result ~200 links
<?php
$stats = [];
$pages = [
(object)['page' => 'http://example.com/?page=123'],
(object)['page' => 'http://example.com/?page=123'],
(object)['page' => 'http://example.com/?page=123'],
(object)['page' => 'http://example.com/?page=321'],
(object)['page' => 'http://example.com/?page=321'],
(object)['page' => 'http://example.com/?page=321'],
(object)['page' => 'http://example.com/?page=qwas'],
(object)['page' => 'http://example.com/?page=safa15'],
]; // array of objects with page property = URL
$params_counter = [];
foreach ($pages as $page) {
$components = explode('?', $page->page);
if (!empty($components[1])) {
parse_str($components[1], $params);
foreach ($params as $key => $val) {
if (!isset($params_counter[$key][$val])) {
$params_counter[$key][$val] = 0;
}
$params_counter[$key][$val]++;
}
}
}
function procentile($percentile, $array)
{
sort($array);
$index = ($percentile/100) * count($array);
if (floor($index) == $index) {
$result = ($array[$index-1] + $array[$index])/2;
} else {
$result = $array[floor($index)];
}
return $result;
}
$some_data = [];
foreach ($params_counter as $key => $val) {
$some_data[$key] = count($val);
}
$procentile = procentile(90, $some_data);
foreach ($pages as $page) {
$components = explode('?', $page->page);
if (!empty($components[1])) {
parse_str($components[1], $params);
arsort($params);
foreach ($params as $key => $val) {
if ($some_data[$key] > $procentile) {
$params[$key] = '$var';
}
}
arsort($params);
$pattern = http_build_query($params);
$new_url = urldecode('?'.$pattern);
if (!isset($stats[$new_url])) {
$stats[$new_url] = 0;
}
$stats[$new_url]++;
}
}
arsort($stats);
I think what OP wants is regex, first you find the domain part in the url using regex, then you can remove the domain part and anything after the matched parts will remain (aka patterns).
for instance,
/^\w*.\w*(.\w*)?/\?search=/
will match the domain part in the url up to the ?search= part, then if you remove them from the whole urls you gonna get the pattern.
however i think it will match all domain-like strings in the url so you might want to change this so you don't remove the necessary part
edited for grammar and stuff
Unfortunately, I think you're out of luck without using pattern matching. You could use a library, or someone else's code for now, but there are just too many variations to solve this problem otherwise. Try this on for size:
function getURLQueryString(url) {
var query_list = {};
var query_strings = url.match(/.*\?(.*)/)[1].split('&');
var i, param;
for(i in query_strings) {
param = query_strings[i].split('=');
query_list[ param[0] ] = param[1];
}
return query_list
}
You'll get back an object in which every key-value pair is a parameter from the query string.

Perform "javascript/jQuery-like" functions using PHP

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.

How to get all php array index from javascript?

I have a php file where I saved all language string. This is the content:
function lang($phrase)
{
static $lang = array(
'step_one' => 'First step',
'step_two' => 'Second step',
... and so on ...
);
return $lang[$phrase];
}
Essentially, when I load a javascript file I want store all array index in a variable like this:
var Lang = <?php echo json_encode(lang()); ?>;
this code line is inserted in a script, this script is available in a php file. Now before of execute this line I have imported the php file where all string translation is available. What I'm trying to achieve, is get all index of this array, in the variable Lang.
Actually I can load a single string traduction from php like this:
lang('step_one');
but how I can save this array in javascript variable?
You can use array_keys to retrieve all array keys. To do that you need your function to return the whole array on request. You can do that with leaving the argument ($phrase) empty and do an if condition with empty in your lang function. You also need to set a default value for $phrase in your function to not raise any errors if you don't pass an argument to the function.
echo json_encode(array_keys(lang());
And the function:
function lang($phrase = "")
{
static $lang = array(
'step_one' => 'First step',
'step_two' => 'Second step',
... and so on ...
);
if(empty($phrase)) {
return $lang;
} else {
if(isset($lang[$phrase])) { //isset to make sure the requested string exists in the array, if it doesn't - return empty string (you can return anything else if you want
return $lang[$phrase];
} else {
return '';
}
}
}
I also added isset to make sure the requested element exists in your language array. This will prevent raising warnings.

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" )

Categories

Resources