Если вы когда-нибудь задумывались, как работают приложения, которые обмениваются данными через интернет (например, мобильное приложение и сервер), то вы на верном пути. RESTful API — это стандартный способ такого общения, и сегодня мы разберем, как создать его на PHP. Не пугайтесь сложных терминов — я объясню всё простыми словами, с примерами и лайфхаками. К концу статьи вы сможете написать свой собственный сервис, который будет принимать запросы, обрабатывать их и возвращать ответы в формате JSON.

Digital-студия WNDER

Что такое RESTful API и зачем он нужен

REST (Representational State Transfer) — это архитектурный стиль, который описывает, как клиент и сервер обмениваются данными. Проще говоря, это набор правил, по которым ваше приложение может попросить у сервера информацию или передать её ему. Представьте, что вы заказываете пиццу: вы (клиент) звоните в пиццерию (сервер), сообщаете, что хотите (запрос), и получаете заказ (ответ). В REST всё аналогично, только роль пиццерии выполняет ваш PHP-скрипт.

Основные принципы REST:

  • Использование HTTP-методов (GET, POST, PUT, DELETE) для разных действий.
  • Каждый ресурс (например, пользователь, заказ) имеет свой URL.
  • Ответы обычно в формате JSON или XML.
  • Сервер не хранит состояние клиента (stateless).

Зачем это нужно? Если вы пишете мобильное приложение, фронтенд на JavaScript или просто хотите, чтобы ваши данные были доступны другим программам, REST — это почти стандарт. Он прост, понятен и легко масштабируется.

Проектируем структуру нашего сервиса

Прежде чем писать код, давайте определимся, что мы будем делать. Возьмём простой пример — сервис для управления списком задач (как в todo-приложении). У нас будут следующие операции:

  • GET /tasks — получить список всех задач.
  • GET /tasks/{id} — получить конкретную задачу.
  • POST /tasks — создать новую задачу.
  • PUT /tasks/{id} — обновить задачу.
  • DELETE /tasks/{id} — удалить задачу.

Для хранения данных используем простую JSON-файл или базу данных (например, MySQL). В этой статье для простоты возьмём файл — так будет легче понять логику.

Структура проекта будет такой:


project/
├── index.php          # точка входа
├── .htaccess          # для перенаправления запросов
└── tasks.json         # файл с данными

Вся логика будет в одном файле index.php — для обучения это нормально. В реальных проектах лучше разделять на классы, но мы не будем усложнять.

Пишем роутер — как обрабатывать запросы

Первое, что нужно сделать — это перенаправить все запросы на наш index.php. Для этого в файле .htaccess (если вы используете Apache) нужно написать:


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Теперь любой запрос попадёт в index.php. Внутри мы должны определить, какой метод и какой URL пришёл. Для этого используем суперглобальные переменные:


$method = $_SERVER['REQUEST_METHOD']; // GET, POST, PUT, DELETE
$uri = $_SERVER['REQUEST_URI']; // например, /tasks/123

Разберём URL на части:


$uri_parts = explode('/', trim($uri, '/'));
// если запрос /tasks/123, то $uri_parts[0] = 'tasks', $uri_parts[1] = '123'

Теперь мы можем написать простой роутер. Например, так:


if ($uri_parts[0] === 'tasks') {
    $id = isset($uri_parts[1]) ? (int)$uri_parts[1] : null;
    switch ($method) {
        case 'GET':
            if ($id) {
                // получить одну задачу
            } else {
                // получить все задачи
            }
            break;
        case 'POST':
            // создать задачу
            break;
        case 'PUT':
            // обновить задачу
            break;
        case 'DELETE':
            // удалить задачу
            break;
    }
} else {
    // 404 Not Found
}

Это основа. Но чтобы не писать всё в одном месте, лучше вынести обработку в отдельные функции или классы. Для нашей статьи оставим в одном файле, но структурируем.

Работа с данными: чтение и запись в файл

Теперь нам нужно хранить задачи. Для простоты будем использовать файл tasks.json. Формат данных:


[
    {"id": 1, "title": "Купить хлеб", "done": false},
    {"id": 2, "title": "Позвонить маме", "done": true}
]

Чтобы прочитать и записать данные, напишем две функции:


function getTasks() {
    $data = file_get_contents('tasks.json');
    return json_decode($data, true); // возвращаем массив
}

function saveTasks($tasks) {
    file_put_contents('tasks.json', json_encode($tasks, JSON_PRETTY_PRINT));
}

Теперь мы можем легко реализовать методы. Например, получить список задач:


if ($method === 'GET' && !$id) {
    $tasks = getTasks();
    echo json_encode($tasks);
    exit;
}

Для создания новой задачи нужно прочитать тело запроса (JSON). В PHP это делается так:


$input = json_decode(file_get_contents('php://input'), true);

А для обновления — просто находим задачу по id и меняем поля.

Безопасность: чего бояться и как защититься

Когда ваш сервис становится доступным из интернета, появляются риски. Вот основные проблемы и решения:

ПроблемаРешение
SQL-инъекции (если используете БД)Используйте подготовленные выражения (PDO)
Подделка запросов (CSRF)Проверяйте токены, используйте HTTPS
Неограниченный доступДобавьте аутентификацию (например, API-ключ)
Чтение чужих данныхПроверяйте права доступа

В нашем примере мы используем файл, поэтому SQL-инъекции не страшны, но нужно валидировать входные данные. Например, для id:


$id = isset($uri_parts[1]) ? (int)$uri_parts[1] : null;

Это защитит от нечисловых значений. Также не забывайте про экранирование вывода, если возвращаете данные в HTML (но у нас JSON — там это не так критично).

Правило: Никогда не доверяйте данным от клиента. Всегда проверяйте и фильтруйте входные данные, даже если вы уверены в источнике.

Обработка ошибок и коды ответов

Хороший API должен возвращать правильные HTTP-коды. Например:

  • 200 OK — успешный запрос
  • 201 Created — ресурс создан
  • 400 Bad Request — неверный запрос
  • 404 Not Found — ресурс не найден
  • 500 Internal Server Error — ошибка на сервере

В PHP можно установить код ответа с помощью функции http_response_code(). Давайте добавим в наш код:


// Если задача не найдена
http_response_code(404);
echo json_encode(['error' => 'Task not found']);

Также полезно обернуть весь код в try-catch, чтобы обрабатывать исключения:


try {
    // основной код
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => $e->getMessage()]);
}

Это позволит не падать с некрасивой ошибкой, а вернуть клиенту адекватный ответ.

Тестирование: как проверить свой API

Для тестирования можно использовать такие инструменты, как Postman, Insomnia или просто curl в терминале. Например, чтобы получить список задач:


curl http://localhost:8000/tasks

А чтобы создать задачу:


curl -X POST http://localhost:8000/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Новая задача"}'

Не забывайте запускать встроенный сервер PHP для разработки:


php -S localhost:8000

Также можно написать простой JavaScript-код для тестирования в браузере:


fetch('http://localhost:8000/tasks')
  .then(response => response.json())
  .then(data => console.log(data));

Это поможет убедиться, что ваш API работает корректно.

Практические советы и лайфхаки

Напоследок поделюсь несколькими советами, которые пригодятся при разработке RESTful API на PHP:

  • Используйте Composer для управления зависимостями — это упростит подключение библиотек.
  • Разделяйте код на слои: маршрутизация, контроллеры, модели. Это облегчит поддержку.
  • Добавьте логирование запросов и ошибок — это поможет в отладке.
  • Для продакшена используйте HTTPS, чтобы шифровать данные.
  • Версионируйте API (например, /v1/tasks), чтобы не ломать совместимость при изменениях.
Лайфхак: Если вы планируете сделать большое API, посмотрите в сторону готовых микрофреймворков, таких как Slim или Lumen. Они уже содержат роутер, middleware и другие полезные вещи — не придётся изобретать велосипед.

Что в итоге

Мы создали простой RESTful сервис на PHP, который умеет выполнять базовые операции с задачами. Вы узнали, как обрабатывать запросы, работать с данными, обеспечивать безопасность и тестировать API. Конечно, это только начало — в реальном проекте понадобится больше функциональности, но фундамент уже заложен.

Не бойтесь экспериментировать: добавляйте новые ресурсы, подключайте базу данных, внедряйте аутентификацию. Практика — лучший способ разобраться.

Если вам нужна помощь с разработкой — обращайтесь в Digital-студию WNDER, мы всегда рады помочь.

© Студия WNDER