简体   繁体   中英

Dynamic PHP geo json example with leaflet js

Greeting all. Here is an example on the Leaflet main site of some GeoJson that is static. I want to make this more dynamic by say swapping out the density node data for something coming from a database (DB). Here is some code showing my attempt at mixing the static code with data retrieved from a DB done in PHP.

$jsonStr = "{\"type\":\"FeatureCollection\",\"features\":[";
    foreach($data as $info){
        if($counter == $count-1){
            $jsonStr .= "
                {\"type\":\"Feature\",\"id\":\"".$info["site_state"]."\",\"properties\":
                    {
                        \"name\":\"".$info["state_dscr"]."\",\"density\":".$info["coalesce"]."
                    }
                }";
        }else{
            $jsonStr .= "
                {\"type\":\"Feature\",\"id\":\"".$info["site_state"]."\",\"properties\":
                    {
                        \"name\":\"".$info["state_dscr"]."\",\"density\":".$info["coalesce"]."
                    }
                },";
        }   
        $counter++;
    }

$jsonStr .= "]}";

$test = json_decode($jsonStr);
//Validate the JSON
if($test === NULL){
    error_log("There is an issue with your json.");
}else{
    header('Content-Type: application/json');
    echo $jsonStr;
}

The above code is run via an D3 json() call like so:

d3.json("js/statesDataJson.php", function(vioData) { ...}

within another js file. And yes my json is missing the state coordinates, which is why i cannot reproduce the choropleth layer found in the example on the leaflet tutorial site (See below link).

This is my attempt at making this example found here more dynamic. I thought i might be able to mix the data from two sources and using the "desnity" node data from one source and use the "geometry" node from the other to build the state layer. That is where i am having problems.
My initial idea is to set up a table in a DB for the geo JSON and continue with my above example of dynamically replicating this .

I am wondering if i am using a canon ball to kill a roach and there is there is a more efficient strategy or solution. Or is the database the only way to dynamically rebuild my json? For example would any advocate trying to parse the json file and edit the density node? Seems ... asinine but i am open to suggestions.

Thank you

There's a much easier and cleaner way of producing and consuming (Geo)JSON in PHP. As Bibhas was pointing out, concatenating strings is very cumbersome and error prone. Building an object in PHP and afterwards encoding it to JSON is very easy. Example:

//php array with data
$phpArray = array(
    array('id' => 'Foo', 'data' => 500),
    array('id' => 'Bar', 'data' => 1000)
);

//jsonString containing geometries
$jsonString = '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[0,0]},"id":"Foo","properties":{"name":"Foo description"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[0,0]},"id":"Bar","properties":{"name":"Bar description"}}]}';

//decode jsonString to jsonObject
$jsonObject = json_decode($jsonString);

//loop through jsonObject
foreach($jsonObject->features as $key => $feature) {
    //check if there is data for this feature
    foreach($phpArray as $row) {
        if ($feature->id == $row['id']) {
            //attach data to feature
            $feature->properties->data = $row['data'];
        }
    }
    //overwrite feature in jsonObject
    $jsonObject->features[$key] = $feature;
}

//encode and output jsonObject
header('Content-Type: application/json');
echo json_encode($jsonObject);

Outputs:

{
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [0, 0]
        },
        "id": "Foo",
        "properties": {
            "name": "Foo description",
            "data": 500
        }
    },{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [0, 0]
        },
        "id": "Bar",
        "properties": {
            "name": "Bar description",
            "data": 1000
        }
    }]
}

Since you're working in/with PHP the easiest thing to do is work with PHP objects. Those you can easily edit, compare, merge, whatever you want to do.

What you are building there, those Feature and FeatureCollection , are GeoJSON . You can find/write a library that takes an array and turns in into GeoJSON. GeoJSON website has a PHP implementation listed under Libraries section. You can find it here inside GeoJSON.class.php . It doesn't have any documentation, but comments are there and the code is fairly simple, you should be able to use the class, and form your own GeoJSON and return it from your server.

If you have spatial extensions and spatial DataTypes in DB you can use the following stack:

  1. Export shape from SQL: SELECT AsWKT(spat0)
  2. Load it using geoPHP
  3. Tranform using geoPHP functions, GEOS native extension or SQL functions
  4. Convert it to GeoJSON using geoPHP again

Or if your database support it, it's so simpler:

  1. SELECT ST_asGeoJSON(the_geom) ...

I needed to do union/diff conversion. Having MySQL 5.5 (these functions are implemented in MySQL since 5.7) I needed to install GEOS lib additionally.

Then it's as simply as:

<?php
include_once('geosPHP/geoPHP.inc');

$wkt1 = $mysqli->query('SELECT AsWKT(shape) FROM table');

$p1 = geoPHP::load($wkt1,'wkt');
$p2 = geoPHP::load('POLYGON((2 2,2 4,4 4,4 2,2 2))','wkt');

$union = $p1->union($p2);
$geojsonConverter = new GeoJSON();
$unionJson = $geojsonConverter->write($union);
$unionJsonObj = $geojsonConverter->write($union, true); // to serve it as object and not string

print "Union of p1&p2 in GeoJson: $unionJson\n";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM