I was curious ab your opinions whats the most efficient transfer format between SpatiaLite and OpenLayers. Currently Im developing an application based on SpatiaLite (extension of SQLite) and OpenLayers and as a transfer format I use GeoJSON.
My procedure:
1) quering DB by php script, using SpatiaLite's function AsGeoJSON, thus obtaining geojson formatted data
2) using php's print() to transfer retrieved data from php variable to JS variable:
$result = $db->query($query);
$r = '{"type": "FeatureCollection","features": [';
while($row = $result->fetchArray(SQLITE3_ASSOC))
{
$r .= '{"type":"Feature","properties":{}, "geometry":' . $row['geometry'] . '},';
}
$r .= ']}';
print'<script> CadastreBorder = ' . $r . '; </script>';
3) creating the features for Vector Layer in OpenLayers by reading
var vectorLayer = new OpenLayers.Layer.Vector(name, {style: style, rendererOptions:
{zIndexing: true}});
var formatGeoJSON = new OpenLayers.Format.GeoJSON({});
vectorLayer.addFeatures(formatGeoJSON.read(CadastreBorder));
map.addLayer(vectorLayer);
Is there any way how to achieve the same goal more efficiently and more nicely?
Thanks!
Not sure about speed, but if you're using recent version of PHP (5.2 >=) you'd might consider using json_encode on php's arrays. Instead of creating string you'd create an array looking somewhere like this:
$geoJSON_array = Array(
"type" => "FeatureCollection",
"features" => Array()
);
And for each row of geometry, add new table to "features":
Array(
"type" => "Feature",
"properties" => Array(),
"geometry" => Array(... your geometry),
)
After creating such array, run json_encode over it and you're home. For safety I'd check it validates (e.g. using http://geojsonlint.com/). This may help you later on, when e.g. there would be need to support new information, or to add new kinds of elements to the map.
Question: Why are you not using fixed strategy for loading points? If you're creating this geoJSON to file/as script, you may also tell openlayers to download it automatically, likes this:
var vectorLayer = new OpenLayers.Layer.Vector(name, {
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: "json/my_geojson.json",
format: new OpenLayers.Format.GeoJSON()
}),
style: style,
rendererOptions: {zIndexing: true}
});
Related
Preconditions:
Programming language: PHP.
Serialization system: Apache avro
PHP library: https://github.com/wikimedia/avro-php
I send various messages via Apache kafka, each message has its own structure (an array with a specific set of keys) and is sent to a strictly defined topic, the data itself is encoded and decoded using Apache avro.
The problem is that the schema itself is transmitted along with the data, which is redundant in my case (Highload), there is no point in this since the client (the consumer of messages from Kafka) owns the schemas for each message structure (one structure - one Kafka topic).
Apparently, the current package https://github.com/wikimedia/avro-php is not suitable.
I'm looking for a ready-made solution - Avro encoder / decoder on PHP, which will allow not sending the schema itself along with the data every time, but substituting it on the client side (it will be stored as a file and substituted depending on the topic). It will save disk space and network traffic.
example of usage current solution:
<?php
require_once('../lib/avro.php');
$schemaJson = <<<_JSON
{"name":"member",
"type":"record",
"fields":[{"name":"foo", "type":"int"},
{"name":"bar", "type":"string"}]}
_JSON;
$item1 = ['foo' => 123, 'bar' => 'ktwop'];
$itemsForSerializing = [$item1];
$avroSchemaForWriter = \AvroSchema::parse($schemaJson);
$writeAvroStringIO = new \AvroStringIO();
$avroIODatumWriter = new \AvroIODatumWriter($avroSchemaForWriter);
$avroDataIOWriter = new \AvroDataIOWriter($writeAvroStringIO, $avroIODatumWriter, $avroSchemaForWriter);
foreach ($itemsForSerializing as $itemForSerializing) {
$avroDataIOWriter->append($itemForSerializing);
}
$avroDataIOWriter->close();
$encodedString = $writeAvroStringIO->string();
echo $encodedString . PHP_EOL . PHP_EOL;
// ACTUAL OUTPUT:
/*
Objavro.codenullavro.schema�{"type":"record","name":"member","fields":[{"name":"foo","type":"int"},{"name":"bar","type":"string"}]} �k����N�*��1�V��ktwop�k����N�*��1�V�
*/
// EXPECTED OUTPUT: ktwop�k����N�*��1�V�
$readAvroStringIO = new \AvroStringIO($encodedString);
$avroDataIOReader = new \AvroDataIOReader(
$readAvroStringIO, new \AvroIODatumReader($avroSchemaForWriter, $avroSchemaForWriter) // HERE I WANT TO USE SCHEMA FROM FILE ON CLIENT SIDE
);
echo "from binary string:" . PHP_EOL;
foreach ($avroDataIOReader->data() as $dataItem) {
echo var_export($dataItem, true) . PHP_EOL;
}
//OUTPUT:
/*
from binary string:
array (
'foo' => 123,
'bar' => 'ktwop',
)
*/
This should do it.
$io = new AvroStringIO();
$writer = new AvroIODatumWriter($schema);
$encoder = new AvroIOBinaryEncoder($io);
$writer->write($data, $encoder);
$io->string();
I'm using the Google Sheets API to write some data into the sheets, but so far either I clear it all and write everything again or I write in new rows (which Sheets API does by default).
I am now writing a single column per run, but I need to get the first available column in the sheet, so I can pass it as the range of writing.
This is my code so far:
$sheet = new \Google_Service_Sheets($this->client);
$range = "'" . $sheetName . "'!" . $rangeArg . (strlen($rangeArg) == 2 ? '' : count($data) + 1000);
$response = $sheet->spreadsheets_values->get($this->sheetId, $range);
if (!$clear && $response && $response->values) {
$c = count($response->values);
$newRange = (intval(substr($rangeArg, 1, 1)) + $c);
$newRange = substr($rangeArg, 0, 1) . $newRange . substr($rangeArg, 2);
$range = "'" . $sheetName . "'!" . $newRange . (count($data) + 1000);
}
$options = ['valueInputOption' => 'RAW'];
if ($clear) {
$sheet->spreadsheets_values->clear($this->sheetId, $range, new \Google_Service_Sheets_ClearValuesRequest);
}
$body = new \Google_Service_Sheets_ValueRange(['values' => $data, 'majorDimension' => $columns ? 'COLUMNS' : 'ROWS']);
$ok = $sheet->spreadsheets_values->append($this->sheetId, $range, $body, $options);
}
I saw someone on the internet mentioning getLastColumn() as a function, but it's not available in my version of sheets API apparently or it's just not in this package.
google/apiclient v2.5.0
google/apiclient-services v0.138
google/auth v1.9.0
getLastColumn is an appscript method. Something like that is not available with the php client library is only going to give you google sheets api methods,
The only way to find out whats on the sheet is to buffer it and scan though as you are already doing. Unfortunately with PHP there is really no easy way of doing it.
$response = $service->spreadsheets_values->batchGet($spreadsheetId);
I dont use PHP, but I am 100% sure, that in Google API its closest things on PHP and Python, just syntax of languages would be different
So for get the first free column through Google Sheet API (using Python):
import httplib2
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
DOCUMENT_ID = '1ma8DG3IQJ377900iaFUPu9qXoThuP22buLgEILVfO1M'
def get_service_sacc():
creds_json = 'param-param-1344-fae81984f8a8.json'
scopes = ['https://www.googleapis.com/auth/spreadsheets']
creds_service = ServiceAccountCredentials.from_json_keyfile_name(creds_json, scopes).authorize(httplib2.Http())
return build('sheets', 'v4', http=creds_service)
sheet_values = get_service_sacc().spreadsheets().values()
_range = "A1:A9"
# or use _range = "Name of List!A1:A9", if u want to take info not from first list of sheets.
write = sheet_values.append(spreadsheetId=DOCUMENT_ID, range=_range, valueInputOption="USER_ENTERED",body={}).execute()
deal_id = str(write['updates']['updatedRange']).split('!')
little info about how get creds.json, if you wanna make thru this method (its from Service Account (https://cloud.google.com/iam/docs/service-accounts), create it, go to you Cloud Developer Console, create a some project, create service account, append it to project, and also after creation, click on three dots at actions (in account line), click Manage keys -> Add key -> Create new key -> json and end it, than download that json, and put it together in one directory of you project where u start you language logic.)
info about, how append works (https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append)
I have some Session values that I am constantly changing via Ajax calls. I can't seem to get a handle on the POST data to process it and set the values.
What I am passing to it here is an array of strings like is shown in my code below.
Here is where AJAX calls:
var sessionValues = [];
str = {"PID": "1", "Level": "Main", "MenuName": "Kitchen", "State": "CHECKED"}
sessionValues.push(str);
var postObj = {"sessionData": sessionValues};
$.ajax({
type: 'POST',
data: {'data': postObj},
url: 'setSession.asp'
}).done(function(response){
console.log(response);
})
I have this working fine in a PHP version of the program but my ASP version is not grabbing the data. Here is my PHP ver and the ASP ver as best as I could convert it.
<-- php setSession.php works fine -->
$data = $_POST['data'];
foreach ($data['sessionData'] as $key => $value) {
$projectProduct = "1";
$level = $value["Level"];
$menuName = $value["MenuName"];
$state = $value["State"];
$_SESSION['PID:'.$projectProduct][$level][$menuName]['menu_state'] = $state;
echo "[PID:".$projectProduct."][".$level."][".$menuName."][".$state."]<br>";
}
0 =>>>>> Array<br>[PID:1][Main][Kitchen][CHECKED]
Here I want to do the same thing in ASP
' setSession.asp
data = Request.Form("data")
For Each part In data("sessionData")
projectProduct = part("PID")
level = part("Level")
menuName = part("MenuName")
state = part("State")
Session("PID:" & projectProduct).Item(level).Item(menuName).Remove("menu_state")
Session("PID:" & projectProduct).Item(level).Item(menuName).Add "menu_state", state
response.write("[PID:" & projectProduct&"]["&level&"]["&menuName&"]["&state&"]<br>")
Next
outputs blank
It looks like it never has any data but doesn't throw any errors. Am I reading the POST object correctly?
[edit]
Here is the RAW POST data captured from Fiddler:
data%5BsessionData%5D%5B0%5D%5BPID%5D=1&data%5BsessionData%5D%5B0%5D%5BLevel%5D=Main&data%5BsessionData%5D%5B0%5D%5BMenuName%5D=Kitchen&data%5BsessionData%5D%5B0%5D%5BState%5D=CHECKED
here I used a URL Decode on that string-
data[sessionData][0][PID]=1&data[sessionData][0][Level]=Main Level Plan&data[sessionData][0][MenuName]=Kitchen&data[sessionData][0][State]=CHECKED
This looks like I should be able to loop through the strings now by using
For Each part In Request.Form("data[sessionData]")
but nothing happens. I added a simple loop to look at the request.form and here is what it is seeing:
for each x in Request.Form
Response.Write(x)
Next
' outputs -> data[sessionData][0][PID]data[sessionData][0][Level]data[sessionData][0][MenuName]data[sessionData][0][State]
I guess what this comes down to is just reading through and processing that string correctly, or multiple if more than one is sent. Correct?
The RAW output definitely helps work out what is going on.
What is happening is jQuery is translating the JSON structure into HTTP POST parameters but during the process, it creates some overly complex key names.
If you break down the key value pairs you have something like
data[sessionData][0][PID]=1
data[sessionData][0][Level]=Main Level Plan
data[sessionData][0][MenuName]=Kitchen
data[sessionData][0][State]=CHECKED
As far as Classic ASP is concerned the this is just a collection of string key and value pairs and nothing more.
The correct approach to work out what these keys are is to do what you have done in the question, but with some minor alternations.
For Each x In Request.Form
Response.Write(x) & "=" & Request.Form(x) & "<br />"
Next
Which when outputted as HTML will look similar to the break down shown above.
Armed with the knowledge of what the keys are you should be able to reference them directly from the Request.Form() collection.
Dim pid: pid = Request.Form("data[sessionData][0][PID]")
Response.Write pid
Output:
1
I am working on some code using Google Maps API. To sum up shortly, I have MySQL database with a table of information used to generate markers on the map. I connected to the database and am using PHP to draw out the necessary attributes and communicate with my Javascript code using XML.
What I'm currently attempting to do is go in the other direction, I'm trying to send a string of information (for example "1,2,3,45,18") from my Javascript code to MySQL to be set as a session parameter (call it #sparam). What is the process behind passing this value to MySQL?
Would I be able to access a MySQL variable through PHP in the same way I can access tables (for the purpose of getting a value back into Javascript)?
I'd appreciate any insight.
Thanks.
EDIT
Maybe I was unclear in my original post. What I'm asking is how would I be able to pass a string to a MySQL session variable, specifically a set of IDs directly related to the IDs in the table of the MySQL database, and then be able to work with these IDs by calling the necessary procedures in MySQL. In turn, the procedures called in MySQL would generate some output, which would then have to be passed back to the Javascript code.
I created a special JSON (JavaScript Object Notation) php pages that I would call from javascript. Then I would parse those JSON responses.
Simple example:
JAVASCRIPT:
function getCheckedUnits() {
jQuery(function($) {
$.ajax( {
url : "page_json.php?action=getsession",
type : "GET",
success : function(data) {
//Get Json and loop over it's data
if (data.length>10){
var jsonData = JSON.parse(data);
$.each(jsonData, function(Idx, Value) {
if (Idx>0){
//get values for each vehicle and then remove it's marker from the map and then add new marker on the map (thereofore update the marker)
c_latitude = Value["lat"];
c_longitude = Value["lon"];
c_name = Value["name"];
c_notes= Value["notes"];
removeMarker(c_name); //remove old marker function
addMarker(c_latitude, c_longitude, c_name); //add current marker function
}
});
}
}
});
});
}
PHP: Here I loop over my arrayList and then create a simple array with values. Then I just output it as a json string
foreach ($listOfCars->arrayList as $key => $value) {
$unit = new fleetUnit();
$unit = $value;
//create array for json output
$data[] = array('lat' => $unit->lat,
'lon' => $unit->lon, 'name' => $unit->name, 'notes' => $unit->notes);
}
echo json_encode($data);
I have to send a two-dimensional JavaScript Array to a PHP page.
Indeed, I'm working on a form-builder, in which the user can add or remove fields.
These fields are added (or removed) using JavaScript (jQuery). When the user is done and hit a 'publish' button, I have to get all the fields concerned and send them to a PHP page which would build a real form with it.
I found a way to do it but I'm pretty sure it's not very clean :
addedFields = new Array();
$("#add-info .field").each(function() {
addedFields.push(new Array($(this).find('.name').val(), $(this).find('.type').val(), $(this).find('.size').val()));
});
Basically, the ".field" class objects are <tr> and the ".name", ".type" and ".size" objects are inputs.
So I get an array of [name, type, size], then I convert it into a string using
addedFields = addedFields.join(";");
Finally, I go to the PHP form that way ;
document.location.href = "create.php?addedfields=" + addedFields;
Concerning the PHP code, I create a PHP array using the explode() function:
$addedFields = explode(";", $_GET['addedfields']);
and then I use it again for each element in the array:
foreach ($addedFields as $field) {
$field = explode(",", $field);
echo "<li>Field with name : '$field[0]', of '$field[1]' type and with a size of $field[2]</li>";
}
So it works, but it seems very dirty...
Use the auto-array feature in PHP:
var data = {};
$("#add-info .field").each(function(i) {
data['field['+i+'][name]'] = $(this).find('.name').val();
data['field['+i+'][type]'] = $(this).find('.type').val();
data['field['+i+'][size]'] = $(this).find('.size').val()]);
});
$.post("target.php", data);
then on the server side
var_dump($_POST['field']);
// array(
// 0 => array(
// 'name' => ...
// 'type' => ...
// 'size' => ...
// ),
// 1 => ...
Edit: slightly more elegant version of the loop:
$("#add-info .field").each(function(i) {
for (attr in {name: 1, type: 1, size: 1}) {
data['field['+i+']['+attr+']'] = $(this).find('.'+attr).val();
}
});
Put those input fields in a form-element. Use JSON like
var formData = $('form').serializeArray();
formData = window.JSON.stringifiy(formData);
$.post('address', {addedfields: formData}, function(){});
something similar to that should do it in jQuery.
on the backend convert the JSON into an object and loop through.
Try consider using JSON to interact data between PHP and JavaScript.
JSON is built into Javascript and there is an awesome library for PHP. Check them out.