Создание API на Albireo CMS
Мы будем считать, что API — это организация URL таким образом, чтобы они могли принимать и отдавать данные с помощью JSON (можно и другого формата). Такое API часто используется для создания сайтов, где фронтендом (front) реализуется с помощью js-библиотек React, Angular, Vue, Svelte и других. С другой стороны на PHP реализуется бэкенд (backend), который принимает и обрабатывает запросы.
Общая схема работы
Не важно, как именно написан front, поскольку в его основе будет лежать fetch-отправка из js-кода, где главное это адрес отправляемого post-запроса.
fetch('https://mysite.com/api/get-products')
.then(res => res.json())
.then(data => console.log(data));
Таким образом, для реализации API следует определиться с адресами.
Структура страниц API
Самый распространенный подход к организации адресов API — это указание его версии, например так:
https://my-site.com/api/ver1/XXX
Где ver1 — это версия API, а XXX — это конкретный метод API.
В Albireo CMS такая структура будет соответствовать такому расположению файлов страниц:
pages/
api/
ver1/
get-products.php
get-users.php
test.php
и т.д.
Пример рабочего API-файла
Страница для API строится по тем же самым правилам, что и любая другая страница. Отличие в том, что api-страница должна возвращать «чистые» данные, без остального обрамления сайта (шапки, подвал и т.п.).
<?php if (!defined('BASE_DIR')) exit('No direct script access allowed');
/**
# заголовок для удобства в админ-панели
title: test@post
# можно использовать любые http-методы из поля _method, либо ALL — для всех методов, включая GET
method: POST
# тип, чтобы не смешивать с другими записями сайта
type: system
# это чистый шаблон без шапок и т.п.
layout: empty.php
# отключаем парсеры контента
parser: -
# можно явно указать адрес
# slug: api/ver1/test
**/
header('Content-Type: application/json');
// Получаем JSON-данные
$input = json_decode(file_get_contents('php://input'), true);
// Проверка
$name = htmlspecialchars($input['name'] ?? 'Гость');
$age = intval($input['age'] ?? 0);
// Ответ
echo json_encode([
'message' => "Привет, $name! Тебе $age лет.",
'success' => true
]);
# end of file
Пример React-формы
Данный пример показывает отправку запроса через React. Обратите внимание на адрес, который указывается в fetch.
/**
...
# в полях страницы подключаем библиотеки из CDN
head[]: <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
head[]: <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
**/
?>
<div id="react-root"></div>
<!-- скрипт можно вынести отдельным js-файлом -->
<script>
const e = React.createElement;
function App() {
const [name, setName] = React.useState('');
const [age, setAge] = React.useState('');
const [response, setResponse] = React.useState(null);
const handleSubmit = (event) => {
event.preventDefault();
fetch('<?= SITE_URL ?>api/ver1/test', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, age })
})
.then(res => res.json())
.then(data => setResponse(data))
.catch(err => setResponse({ message: 'Ошибка', success: false }));
};
return e('div', null,
e('form', { onSubmit: handleSubmit },
e('input', {
type: 'text',
placeholder: 'Имя',
value: name,
onChange: e => setName(e.target.value)
}),
e('input', {
type: 'number',
placeholder: 'Возраст',
value: age,
onChange: e => setAge(e.target.value)
}),
e('button', { type: 'submit' }, 'Отправить')
),
response && e('p', null, response.message)
);
}
ReactDOM.render(e(App), document.getElementById('react-root'));
</script>
Создание frontend
Данный пример показывает, что Albireo CMS может работать как backend, так и frontend. В примере мы подключаем библиотеку React из CDN, но на практике скорее всего будет использоваться локальная компиляция NodeJS, после которой на выходе будет единый js-файл, который и нужно будет подключить к странице.
Если разместить файл в каталоге шаблона assets/js, то подключить его можно через поля страницы (есть и другие способы). Тоже самое касается и css-файла в каталоге assets/css.
# в конце BODY js.lazy[]: main.js # секция HEAD css.head[]: main.css
И html-код, который задаёт контейнер, в произвольном месте страницы:
<div id="react-root"></div>
Таким образом при компиляции NodeJS достаточно указать места расположения итоговых js/css-файлов, чтобы они автоматически подключились к странице.
Для предотвращения браузерного кэширования файлов на этапе разработки можно использовать get-параметр с меткой времени js.lazy[]: main.js?<?= time() ?>