Spatial database :: PostGIS

Voyons comment utiliser l'extension PostGIS de PostgreSQL pour stocker et gérer de l'information géographique dans un SGBD.

Installation avec OpenShift

Déployer une application PHP/PGSQL+PostGIS avec OpenShift (https://www.openshift.com)

Créer un compte OpenShift par ce lien : https://openshift.redhat.com/app/account/new?then=%2Fapp%2Fconsole

Suivre le lien “Create first application now”

Choisir le cartdrige PHP5.4

Définir un nom de domaine rhcloud.com et le nom de préfixe correspondant à l'application (ex. geoinf-oertz.rhcloud.com)

(remarque : si la création prend du temps, démarrer les points 2 et 3 en parallèle)

A la question “Will you change your code ...”, répondre non

Depuis la web console et dans la configuration de l'application, ajouter le cartdrige PostgreSQL 9.2

Conserver les crédentials

Installer pgadmin : http://www.pgadmin.org/

Installer le client tool rhc : https://developers.openshift.com/en/getting-started-overview.html

Lancer une session rhc en ligne de commande depuis une console OS :

Exécuter :

rhc setup

Valider le server name par défaut

Saisir le login OpenShift et mot de passe

A la question sur le token, pour éviter la resaisie de mot de passe, répondre oui

A la question sur la paire de clés SSH, répondre oui

Exécuter :

rhc port-forward -a myAppName

Lancer pgadmin

Créer une connexion sur l'IP (et le port) forwardée par la commande ci-dessus sur la ligne PostgreSQL

Saisir les crédentials et se connecter

Vérifier le nombre de tables dans la BD (normalement aucune)

Exécuter dans la console SQL :

create extension postgis;

Vérifier le nombre de tables, de vues et de fonctions (normalement beaucoup)

Tout est prêt !

Une première "geotable"

Créer une géotable

CREATE TABLE my4capitals (id serial PRIMARY KEY, name text);
SELECT AddGeometryColumn( 'my4capitals', 'the_geom', 4326, 'POINT', 2 );

Alimenter la table (cf. http://fr.wikipedia.org/wiki/Well-known_text)

INSERT INTO my4capitals VALUES ( nextval('my4capitals_id_seq'), 'Paris', ST_GeometryFromText( 'POINT(2.333 48.867)', 4326));
INSERT INTO my4capitals VALUES ( nextval('my4capitals_id_seq'), 'Bern', ST_GeometryFromText( 'POINT(7.433 46.95)', 4326));
INSERT INTO my4capitals VALUES ( nextval('my4capitals_id_seq'), 'Rome', ST_GeometryFromText( 'POINT(12.5 41.883)', 4326));
INSERT INTO my4capitals VALUES ( nextval('my4capitals_id_seq'), 'Madrid', ST_GeometryFromText( 'POINT(-3.71 40.41)', 4326));

Lire la table et ses données géographiques

SELECT ST_AsEWKT(the_geom) FROM my4capitals;
SELECT ST_AsText(the_geom) FROM my4capitals;
SELECT ST_AsGeoJSON(the_geom) FROM my4capitals;

Transformer des coordonnées d'une projection à une autre

SELECT ST_AsEWKT(ST_Transform(the_geom, 21781)), ST_AsEWKT(the_geom) FROM my4capitals;

Géoservice Get4Capitals.php

Cet exemple montre comment créer un service sur mesure qui va publier l'information géographique de la géotable. Il est notamment fait usage du format GeoJSON pour transmettre ces données au client. OpenLayers saura par exemple l'exploiter facilement au travers d'une couche ol.Vector et le format ol.format.GeoJSON.

<?php
require_once 'GeoManager.php';
$conn = new Connection("host=127.0.0.1 port=5432 dbname=php user=admintoto password=blablatutu");
$query = "SELECT name, ST_AsGeoJSON(the_geom) from my4capitals";
$result = $conn->selectQuery($query);
$i = 0;
$fc = new FeatureCollection();
while ($row = pg_fetch_row($result)) {
$fc->addFeature(new Feature($i++, (json_decode($row[1])), array("name" => $row[0])));
}
echo json_encode($fc);
?>

On a besoin d'un GeoManager (GeoManager.php) qui sait gérer les requêtes avec la geodatabase et encoder les résultats par un flux GeoJSON.

<?php
class Connection {
private $CONFIG;
private $CONN;
function __construct($cfg) {
$this->CONFIG = $cfg;
return $this->CONN = pg_connect($this->CONFIG) or die('connection failed');
}
function selectQuery($query) {
$result = pg_query($this->CONN, $query);
if (!$result) throw new ErrorException($query);
return $result;
}
function insertQuery($query) {
pg_query($this->CONN, "BEGIN WORK");
$result = pg_query($this->CONN, $query);
if (!$result) {
pg_query($this->CONN, "ROLLBACK");
} else {
pg_query($this->CONN, "COMMIT");
}
}
}
class Feature
{
var $type;
var $geometry;
var $id;
var $properties;
function Feature($id,$geom,$properties) {
$this->type = "Feature";
$this->geometry = $geom;
$this->id = $id;
$this->properties = $properties;
}
}
class FeatureCollection
{
var $type;
var $features;
function FeatureCollection()
{
$this->type = "FeatureCollection";
$this->features = array();
}
function addFeature($feature) {
array_push($this->features,$feature);
}
}
?>

TODO

Tester ce géoservice et analyser les différentes étapes du processus (veiller à reconfigurer les paramètres de connexion)

Terminer l'exemple en exploitant le géoservice dans OpenLayers avec une ol.layer.Vector comme vu dans Ex5A.