Encapsuler l'API OpenWeatherMap dans une source de données
1Présentation
Dans ce tutoriel, nous verrons comment créer un objet utilisable comme source de données. Pour l'exemple, nous allons faire un objet qui s'interface avec l'API du service OpenWeatherMap, permettant de récupérer la météo actuelle de n'importe quel lieu (pour être précis, l'API OpenWeatherMap prend en paramètre une latitude et une longitude ; on utilisera donc l'API Geocoding pour obtenir les coordonnées géographiques de la ville demandée).
2Configuration
Dans le fichier de configuration etc/temma.php, on va ajouter la définition d'une source de données un peu spéciale. Comme il ne s'agit pas d'une source de données gérée nativement par Temma, on va préfixer le DSN du nom de l'objet à utiliser (entre crochets).
Le DSN sera de la forme openweather://API_KEY
API_KEY étant la clé d'API fournie par OpenWeatherMap.
Exemple de configuration :
<?php
return [
"application" => [
"dataSources" => [
"meteo" => '[\OpenWeatherMap\Weather]openweather://0123456789abcdef0123456789abcdef'
]
]
];
3Code source
Voici le code de notre source de données, que l'on enregistrera dans le fichier lib/OpenWeatherMap/Weather.php :
<?php
namespace OpenWeatherMap;
class Weather extends \Temma\Base\Datasource {
/** Constante : préfixe du DSN. */
const DSN_SCHEME = 'weather://';
/** Constante : URL de l'API OpenWeatherMap data. */
const DATA_API_URL = 'https://api.openweathermap.org/data/2.5/weather';
/** Constante : URL de l'API OpenWeatherMap geocoding. */
const GEO_API_URL = 'http://api.openweathermap.org/geo/1.0/direct';
/** Clé d'accès à l'API. */
private $_key = null;
/**
* Factory. Crée une instance de l'objet à partir d'un DSN.
* @param string $dsn Chaîne de configuration.
* @return \OpenWeatherMap\Weather L'objet instancié.
* @throws \Exception Si le DSN est incorrect.
*/
static public function factory(string $dsn) : \OpenWeatherMap\Weather {
if (!str_starts_with($dsn, self::DSN_SCHEME)) {
throw new \Exception("Invalid OpenWeatherMap DSN '$dsn'.");
}
$key = mb_substr($dsn, mb_strlen(self::DSN_SCHEME));
return (new self($key));
}
/**
* Constructeur.
* @param string $key Clé d'API.
*/
public function __construct(string $key) {
$this->_key = $key;
}
/**
* Recupère la météo d'un lieu.
* @param string $place Lieu, sous la forme "Ville" ou "Ville, Pays" ou "Ville, Région, Pays".
* @param mixed $default Paramètre inutilisé (nécessaire pour des raisons d'héritage).
* @param mixed $options Paramètre inutilisé (nécessaire pour des raisons d'héritage).
* @return mixed Tableau associatif contenant les données météorologiques.
* @throws \Exception Si une erreur est survenue.
*/
public function get(string $place, mixed $default=null, mixed $options=null) : mixed {
// récupération des données géographiques
$query = http_build_query([
'appid' => $this->_key,
'limit' => 1,
'q' => $place,
]);
$result = file_get_contents(self::GEO_API_URL . '?' . $query);
$geo = json_decode($result, true);
if (!isset($geo[0]['lat']) || !isset($get[0]['lon']) {
throw new \Exception("Unable to get geographic data for '$place'.");
}
// récupération des données météorologiques
$query = http_build_query([
'appid' => $this->_key,
'lat' => $geo[0]['lat'],
'lon' => $get[0]['lon'],
'units' => 'metric',
]);
$result = file_get_contents(self::DATA_API_URL . '?' . $query);
$weather = json_decode($result, true);
if (!isset($weather['main']['temp']))
throw new \Exception("Unable to get weather data for '$place'.");
return [
'temperature' => $weather['main']['temp'],
'ressentie' => $weather['main']['feels_like'],
'pression' => $weather['main']['pressure'],
'humidite' => $weather['main']['humidity'],
];
}
}
- Lignes 21 à 27 : Méthode factory(), appelée par Temma lors de la création de la source de données. Cette méthode interprète le DSN et appelle le constructeur.
- Lignes 32 à 34 : Constructeur, utilisable pour créer une instance de l'objet directement.
- Lignes 43 à 72 : Méthode get(), qui surcharge celle de l'objet parent \Temma\Base\Datasource. Cette méthode est utilisable directement, mais elle est aussi appelée automatiquement lors d'une lecture de type tableau.
- Lignes 45 à 54 : Connexion à l'API Geocoding, pour obtenir la latitude et la longitude de la ville demandée.
- Lignes 56 à 65 : Connexion à l'API OpenWeatherMap, pour obtenir les informations météorologiques à partir de la latitude et la longitude récupérées précédemment.
4Utilisation
Dans un contrôleur, la source de données qui a été nommée "meteo" dans le fichier de configuration
est disponible en écrivant $this->meteo
. La récupération des informations
météorologiques peut s'écrire en appelant la méthode get() ou avec l'écriture de type tableau :
// utilisation de la méthode get()
$data = $this->meteo->get('Paris, FR');
// écriture de type tableau
$data = $this->meteo['Paris, FR'];
Dans un autre objet, il faut passer par le composant d'injection de dépendances :
$data = $this->_loader->dataSources->meteo->get('Paris, FR');
$data = $this->_loader->dataSources->meteo['Paris, FR'];
Les données récupérées sont stockées dans un tableau associatif :
printf(" Température mesurée : %f °C\n", $data['temperature']);
printf(" Température ressentie : %f °C\n", $data['ressentie']);
printf("Pression atmosphérique : %f hPa\n", $data['pression']);
printf(" Humidité : %f %%\n", $data['humidite']);