Data API - getData, datové body
CMS se snaží oddělit datový model od aplikace. Nejde o databázi, ale o separaci logiky pro získání a přípravy dat. Zatím není plně odděleno. Nikdy zatím nenastal požadavek oddělení databíze na jiném serveru.
Koncept
V adresáři CONFIG['dataDir'] jsou kontrolery pro získávání dat s veškerou logikou kolem. To znamená, že např. tagy si tímto zavolají datový bod a získají kolekci dat, která již bude připravena pro šablony.
Tento datový bod je volán jak z PHP, tak z front-endu pomocí JS příkazu fetch.
Většinou jsou data vrácena v JSON formátu.
Konfigurace
V config/data.yaml definujte adresář pro kontrolery dotazů a případný url odkaz vzdáleného stroje:
dataDir: /app/DATA
dataRemoteUrl:
Router
Ukázka z app/routes/data.php:
const GET_DATA_URL = '/getData';
$cors = (!Ip\isIpAllowed(explode(',', env('ALLOWED_IP', '')))) ? '*' : '*';
Response\cors($cors);
$routes = [
Route\any($path, DATA_DIR . str_replace(GET_DATA_URL, '', $path) . '.php'),
Diactoros\text($_SERVER['REQUEST_URI'] . " — not found", 404),
];
$response = Route\matching($routes);
Systém automaticky mapuje URL na soubory dle adresářové struktury. Například:
- /getData/EXAMPLES/get-example?param=value → app/DATA/EXAMPLES/get-example.php
V POST požadavcích je třeba řešit kontrolu metody v samotném kontroleru.
Volání z frontendu (JavaScript)
GET požadavek
fetch('/getData/EXAMPLES/get-example?letter=a&number=1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
POST požadavek
const url = '/getData/EXAMPLES/post-example?test=72';
const data = {
name: 'John Doe',
email: 'johndoe@example.com',
message: 'Hello, world!'
};
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
};
fetch(url, options)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Volání z PHP skriptů
Zde je komplikovanější. Pokud se jedná o vzdálený server, musí se použít curl, a pokud jde o místní server ve stejné instanci, volají se skripty přímo.
Využívá se core/Data/Data.php a funkce get() a post(). Na vzdáleném serveru pak bude třeba poladit CORS.
Při tomto způsobu volání skriptů přímo z PHP vzniká problém, že data nepřichází v POST a GET požadavku. Zatím tedy definuji u volání require proměnné $_get nebo $_post.
GET
use Petrovo\Data;
use Siler\Encoder\Json;
$query = [
'content' => PAGE_INFO['content_id'],
'lang' => LANG,
];
$output = Data\get('EXAMPLES/get-example?' . http_build_query($query));
// následuje zpracování vrácených dat ve skriptu
$ziskane = Json\decode($output);
POST
use Petrovo\Data;
use Siler\Encoder\Json;
$data = [
'name' => 'John Doe',
'phone' => '123456789',
'city' => 'Prague',
'lang' => LANG,
];
$output = Data\post('EXAMPLES/post-example', $data);
$ziskane = Json\decode($output);
Tvorba datového endpointu
Datové endpointy jsou umístěny v app/DATA/ a mají přístup k $_get a $_post:
<?php
declare(strict_types=1);
use Petrovo\Data;
// Přístup k parametrům
$id = $_get['id'] ?? null;
$name = $_post['name'] ?? null;
// Logika pro získání dat
$result = [
'status' => 'success',
'data' => [
'id' => $id,
'name' => $name,
]
];
return Data\outputJson($result);
CORS a IP filtrování
Přístup je kontrolován dle CORS nastavení a IP filtrování definovaného v .env:
ALLOWED_IP=127.0.0.1,::1,93.185.102.4
CORS_ORIGINS=
Remote data server
Pokud je v konfiguraci definován dataRemoteUrl, budou se data volat na vzdáleném serveru přes HTTP request. Lokálně budou tagy/kontrolery přijímatelné bez přímého přístupu k databázi.