простой api на php
В данной статье вы узнаете, как создать простой REST API в PHP.
1. Обзор проекта
1.1 Что такое REST API?
REST API позволяет вашему приложению взаимодействовать с одним или несколькими различными приложениями, используя концепции REST.
1.2 Зачем нужен REST API?
Во многих приложениях REST API необходим, потому что это самый легкий способ создания, чтения, обновления или удаления информации между различными приложениями через Интернет или протокол HTTP. Эта информация представляется пользователю в одно мгновение, особенно если вы используете JavaScript для отображения данных на веб-странице.
1.3 Где используется REST API?
REST API может использоваться любым приложением, которое может подключаться к Интернету. Если данные из приложения могут быть созданы, прочитаны, обновлены или удалены с помощью другого приложения, это обычно означает, что используется REST API.
2. Файловая структура
3. Настройка базы данных
3.1 Создание таблицы категорий
3.2 Дамп данных для таблицы категорий
3.3 Создание таблицы товаров
3.4 Дамп данных для таблицы товаров
3.5 Подключение к базе данных
Приведенный ниже код показывает учетные данные базы данных и метод для получения подключения к базе данных с помощью PDO.
Создайте папку api и откройте её. Создайте папку config и в ней создайте файл database.php со следующим кодом.
4. Получение товаров
4.1 Создание объекта Product
Код ниже содержит класс с именем Product и несколько свойств. Также показан метод конструктора, который принимает соединение с базой данных.
4.2 Создание файла для чтения товаров
Код ниже содержит заголовки о том, кто может читать этот файл и какой тип содержимого он будет возвращать.
4.3 Подключение к базе данных и таблице товаров
Замените комментарий // подключение к базе данных будет здесь в файле read.php следующим кодом.
4.4 Чтение товаров из базы данных
Замените комментарий // чтение товаров будет здесь в файле read.php следующим кодом.
4.5 Создание метода read()
4.6 Уведомление пользователя о том, что товары не найдены
Замените комментарий // ‘товары не найдены’ будет здесь в файле read.php следующим кодом.
5. Создание товаров
5.1 Создание файла create.php
Откройте папку product и создайте в ней файл create.php со следующим содержимым.
5.2 Создание метода create()
6. Получение одного товара
6.1 Создание файла read_one.php
6.2 Создание метода readOne()
7. Обновление товара
7.1 Создание файла update.php
7.2 Создание метода update()
8. Удаление товара
8.1 Создание файла delete.php
Откройте папку product и создайте файл delete.php со следующим содержимым.
8.2 Создание метода delete()
9. Поиск товаров
9.1 Создание файла search.php
В папке product создайте файл search.php со следующим кодом.
9.2 Создание метода search()
10. Пагинация товаров
10.1 Создание файла read_paging.php
В папке product создайте файл read_paging.php со следующим кодом.
10.2 Создание файла core.php
Этот файл содержит нашу базовую конфигурацию, такую как базовый URL и переменные пагинации.
Откройте папку config и создайте в ней файл core.php со следующим содержимым.
10.3 Создание метода readPaging()
10.4 Создание метода count()
Так же в классе Product (файл product.php) добавьте метод count() для создания массива пагинации.
10.5 Получение массива пагинации
11. Получение категорий
11.1 Создание объекта Category
Откройте папку objects и создайте новый файл category.php со следующим кодом.
11.2 Создание файла read.php
Создайте новую папку category в корне, и в ней файл read.php со следующим кодом.
11.3 Создание метода read()
Если вам понравилась данная статья, рекомендую к прочтению создание регистрации и авторизации в php с использованием JWT.
Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.
Взаимодействие сервисов и REST API
В современной веб-разработке принято разделять backend-разработку (то, что выполняется на сервере – например, приложение на PHP) от frontend-разработки (то, что выполняется в браузере пользователя – JavaScript). Frontend выполняет запросы на backend и отрисовывает данные, которые backend ему возвращает. Но каким образом происходит этот обмен? Чем они обмениваются? Как выглядят данные, которые передаются между бэкендом и фронтендом? Об этом и пойдёт речь в данном уроке.
В уроке про composer мы с вами уже сталкивались с форматом JSON. И я вам в том уроке советовал погуглить об этом формате. Еще не сделали этого? Тогда сейчас – самое время.
Пишем API
В этом уроке мы с вами напишем простейшее API для работы со статьями.
Первое, что нам следует сделать – это создать новый фронт-контроллер, который будет предназначен специально для работы в формате JSON.
И рядом с ним файл index.php
Проверяем, что всё работает, перейдя по адресу: http://myproject.loc/api/
Теперь попробуем вывести что-нибудь в формате json.
В PHP есть встроенные функции для работы с json. Нас будут интересовать прежде всего две: json_encode() и json_decode(). Первая позволяет представить какую-то сущность в json-формате.
Обновим страничку и увидим следующее:
Кроме того, когда сервер отвечает в фомате JSON, стоит отправлять соответствующий заголовок клиенту:
Теперь поставьте в свой браузер расширение JSON formatter.
И снова обновите страничку. Вы увидите, что ответ сервера стало гораздо проще читать – это расширение добавляет форматирование, чтобы ответ было легче воспринимать человеку.
Теперь давайте сделаем наш API в ООП-стиле. Мы будем использовать ту же архитектуру MVC, в которой компонент View вместо рендеринга HTML-шаблонов будет выводить JSON. Давайте сделаем у View метод для вывода JSON-а.
Теперь создадим контроллер, который позволит работать со статьями через API. Создаём сначала папку Api внутри Controllers, а затем добавляем наш новый контроллер:
Теперь создаём отдельный роутинг для API:
И, наконец, пишем фронт-контроллер для API.
Всё, теперь можно зайти на наш API и проверить как выводится статья: http://myproject.loc/api/articles/1
Добавляем реализацию интерфейса:
и добавляем метод, который представит объект в виде массива:
Postman
Но что, если мы захотим изменить нашу статью с помощью API? Для этого нам нужно отправить в API запрос в формате JSON. В реальном приложении для этого используется фронтенд на JS. А в целях разработки – специальные инструменты, позволяющие отпралять такие запросы. Одним из таких инструментов является приложение Postman. Скачайте, установите и запустите.
В контроллере добавим еще один метод:
Здесь php://input – это входной поток данных. Именно из него мы и будем получать JSON из запроса. file_get_contents – читает данные из указанного места, в нашем случае из входного потока. А json_decode декодирует json в структуру массива. После чего мы просто выводим массив с помощью var_dump().
Добавляем для него роут:
И заполняем Postman данными, как на скриншоте:
После этого жмём кнопку Send. Прокручиваем ниже до ответа и выбираем вкладку Preview.
Тут мы видим вывод var_dump той структуры, которую мы отправили в POST-запросе в формате JSON.
Давайте вынесем функционал чтения входных данных в абстрактный контроллер:
И теперь во всех контроллерах мы сможем получать входные данные вот так:
Давайте теперь сделаем функционал, который позволит сохрянять в базу данных статью, пришедшую в формате JSON.
Разумеется, здесь также стоит добавить авторизацию и проверять, является ли авторизованный пользователь тем, кто указан в авторе статьи. Но это учебный и упрощенный пример, который показывает сам принцип работы с JSON-API.
Снова возвращаемся в Postman и повторно жмем Send.
Прокручиваем вниз до ответа, но на этот раз переходим во вкладку Pretty.
Как видим, статья успешно добавилась и выводится в формате JSON по адресу http://myproject.loc/api/articles/id_статьи.
REST API
То что мы сейчас с вами написали – это простейший учебный пример API. Есть более сложные системы для реализации API. Они позволяют привязывать роутинг к конкретному типу запроса. Например, POST-запрос по адресу http://myproject.loc/api/articles/1 вызовет в контроллере экшн update, который будет обновлять статью с А GET-запрос по тому же адресу будет вызывать экшн view, который будет просто возвращать статью.
То есть для одного и того же адреса мы отправляем разные типы запросов – POST, GET, PUT, DELETE. И в зависимости от типа запроса будут вызваны разные экшены. В рамках текущего курса мы этого делать не будем – ограничимся простым примером, чтобы вы просто понимали концепцию.
При этом структура запроса и ответа как правило одинаковые – мы можем посмотреть статью в формате JSON. Чтобы обновить её – мы тоже отправляем статью в формате JSON, с теми же полями.
Вот этот стиль взаимодействия с API в формате JSON, когда мы используем одну и ту же структуру данных для запроса и ответа, и используем разные типы запросов для разных действий – называется REST API. Запомните это, об этом могут спросить на собеседовании: «Что такое REST API». И вы скажете, что это когда:
Заключение
Стоит отметить, что API используется не только для взаимодействия между фронтендом и бэкендом, но еще и для взаимодействия между разными сервисами на бэкенде. В одном проекте может быть несколько приложений на бэкенде, которые общаются между собой по API. Один сервис отправляет в другой сервис сообщение в JSON-формате. Тот его принимает и преобразует JSON в данные для работы.
Создание современного API на PHP в 2020 году
Итак, на примере этого API, я хочу показать современную PHP архитектуру для высоконагруженных проектов. Когда проект еще в самом начале, и не то, что бизнеслогика (взаимоотношения с базой данных) не прописана, но и сама бизнес модель не очень ясна, построение эффективной IT архитектуры может идти только одним путем: необходимо жестко разделить frontend и backend.
Что обычно делали в таких ситуациях два-три года назад? Брался монолитный фрейворк типа Laravel или Yii2, вся бизнес модель разбивалась, худо-бедно, на блоки, а эти блоки уже имплементировались как модули фреймворка. В итоге еще через 3 года получалась огромная не поворотная машина, которая сама по себе медленная, а становилась почти невыносимо медленной, в которой фронтенд рендится через бэкенд посредством классической MVC архитеркутуры (пользователь отправил запрос, контроллер его подхватил, вызвал модель, та в свою очередь чего-то там натворила с базой данных, вернула все контроллеру, а тот наконец-то вызвал вьювер, вставил туда данные из модели и отдал это все пользователю, который уже успел открыть очередную банку пива. ). А… ну еще особо продвинутые ребята, они не просто вьюверели Tweeter Bootstrap, а во вьювер вкручивали на самом деле очень хорошие библиотеки типа JQuery или вместо вьювера использовали какой-нибудь фронтенд фреймворк. В итоге поддерживать такой БеЛаЗ становилось все сложнее, а ввести нового программиста в команду было очень сложно, ибо не все рождаются Энштейнами. Добавим сюда тотальное отсутствие документации разработчика (камменты в 9000 файлах почитаешь — там все есть!) и в итоге, смотря на это все, становилось по-настоящему грустно…
Но тут произошел ряд событий, который в корне изменил ситуацию. Во-первых, наконец-то, вышли стандарты PSR и Symfony внезапно перестал быть единственным модульным фремворком, во-вторых, вышел ReactJS, который позволил полноценно разделить фронтенд от бэкенда и заставить их общаться через API. И добивая последний гвоздь в крышку гроба старой системы разработки (MVC — это наше все!) выходит OpenAPI 3.0, собственно, который и регулирует стандарты этого общения через API между фронтендом и бэкендом.
И в мире PHP стало возможно делать следующее:
Теперь становятся вопросы, точнее два вопроса, а что у нас перед API и соответственно, что у нас «под хвостом» после API.
1.«Там вдали за рекой», далеко перед API у нас цветет, расползается на новую функциональность и картинки — ФРОНТЕНД (Предпочтительнее ReactJS, но Vue тоже сойдет. Хотя там из коробки всего столько много, что утяжелять процесс он будет, а вот насколько в реальной жизни это понадобится — не совсем понятно и зависит напрямую от бизнес модели). И НЕТ! Я к этому зверю даже близко подходить не буду, ибо с детства у меня на него аллергия. Тут нужен отдельный специалист. Я не фулстак и не пишу фронтенд.
2. Прямо вот перед самим API у нас… НЕ УГАДАЛИ… не NGINX, а RoadRunner roadrunner.dev/features. Заходим, читаем, понимаем, что это быстрее и вокеры расписываются по количеству процессоров, а посему никогда не будет таблички «МЫ НА ПРОФИЛАКТИКЕ», ибо просто надо вокеры переключить.
И на этом моменте хочу остановиться подробнее. Ибо в моем понимании есть три пути «как мух ловить», запросы то бишь…
1. В случае если весь API написан уже, и будет написан в дальнейшем, на PHP — голову ломать не зачем, ставим RoadRunner с prometheus.io
2. В случае, если система собирается из разных кусков, разные сервисы написаны на разных языках и дальше тоже не понятно на чем их писать будут:
2.1. Ставим NGINX UNIT — пользуемся поддерживаемыми языками.
2.2. Поднимаем ВСЕ РАВНО КАКУЮ систему контейнеров, Docker, LXC, LXD. Выбор опять же зависит от размера проекта — поддерживать сборку PROXMOX-LXC на хостинге в 12 процессоров, c 32Гб памяти, за 40 евро в месяц будет в разы дешевле, чем Docker сборки на Google Cloud Platform. В каждый контейнер ставим подходящий к языку сервер, и связываем все это HAProxy www.haproxy.org. HAProxy — шикарный балансер и прокси сервер который в корпоративной среде, не менее популярен, чем NGINX. Что он делает, а чего нет, читаем тут cbonte.github.io/haproxy-dconv/2.3/intro.html пункт 3.1. При такой архитектуре сервисы или микросервисы могут писаться на чем угодно и никто не зависит от ограничений накладываемыми RoadRunner или NGINX UNIT.
3. «Под хвостом» — Cycle ORM. Не ленимся, смотрим видео, что будет стоять за ней конкретно MySQL или PostgreSQL- опять, я бы оставил на после того, как будет понятна бизнес схема проекта. MySQL проще масштабируется, в PostgreSQL — больше бизнес логики перенесенной внутрь самой базы.
4. Пример, который можно посмотреть и пощупать. Там за основу взято тестовое задание. Все самые полезные вещи находятся в папке EXTRAS. Там уже есть jar file генератора, YAML swagger файл API, сгенерированный API stub через OpenAPITools в SLIM4. Даже с аутентификацией и middleware. Документация на API сгенрированная, правда swagger, не OpenAPITools. Предполагается, что некоторые юзеры залогинены и им выдан токен. Там уже стоит RoadRunner впереди. Стек — PHP 7.4.10, PostgreSQL 12.4.
Пишем свой API для сайта с использованием Apache, PHP и MySQL
С чего все началось
Разрабатывая проект, я столкнулся с необходимостью организации клиент-серверного взаимодействия приложений на платформах iOS и Android с моим сайтом на котором хранилась вся информация — собственно БД на mysql, картинки, файлы и другой контент.
Задачи которые нужно было решать — достаточно простые:
регистрация/авторизация пользователя;
отправка/получение неких данных (например список товаров).
И тут-то мне захотелось написать свой API для взаимодействия с серверной стороной — большей своей частью для практического интереса.
Входные данные
В своем распоряжении я имел:
Сервер — Apache, PHP 5.0, MySQL 5.0
Клиент — Android, iOS устройства, любой браузер
Я решил, что для запросов к серверу и ответов от него буду использовать JSON формат данных — за его простоту и нативную поддержку в PHP и Android. Здесь меня огорчила iOS — у нее нет нативной поддержки JSON (тут пришлось использовать стороннюю разработку).
Внешний вид запросов решено было сделать таким:
http://[адрес сервера]/[путь к папке api]/?[название_api].[название_метода]=[JSON вида <«Hello»:«Hello world»>]
Путь к папке api — каталог на который нужно делать запросы, в корне которого лежит файл index.php — он и отвечает за вызов функций и обработку ошибок
Название api — для удобства я решил разделить API группы — пользователь, база данных, конент и тд. В таком случае каждый api получил свое название
Название метода — имя метода который нужно вызвать в указанном api
JSON — строковое представление JSON объекта для параметров метода
Скелет API
Скелет API на серверной стороне состоит из нескольких базовых классов:
index.php — индексный файл каталога в Apache на него приходятся все вызовы API, он осуществляет парсинг параметров и вызов API методов
MySQLiWorker — класс-одиночка для работы с базой MySQL через MySQLi
apiBaseCalss.php — родительский класс для всех API в системе — каждый API должен быть наследован от этого класса для корректной работы
apiEngine.php — основной класс системы — осуществляет разбор переданных параметров (после их предварительного парсинга в index.php) подключение нужного класса api (через require_once метод), вызов в нем нужного метода и возврат результата в JSON формате
apiConstants.php — класс с константами для api вызовов и передачи ошибок
apitest.php — тестовый api для тестирования новых методов перед их включением в продакшн версию
Теперь подробней о каждом
Я попробовал достаточно документировать файлы, чтобы не занимать много место под текст. Однако в тех файлах где нет комментариев, я все ж приведу описание.
Index.php
Как уже говорил раньше это входной индексный файл для Apache а значит все вызовы вида www.example.com/api будет принимать он.
Первым делом устанавливаем тип контента — text/html (потом можно сменить в самих методах) и кодировку — UTF-8.
Дальше проверяем, что у нас что-то запрашивают. Если нет то выводим JSON c ошибкой.
Если есть параметры запроса, то подключаем файл движка API — apiEngine.php и создаем класс движка с переданными параметрами и делаем вызов api метода.
Выходим из цикла так как мы решили что будем обрабатывать только один вызов.
apiEngine.php
Вторым по важности является класс apiEngine — он представляет собой движок для вызова api и их методов.
apiConstants.php
Данный класс используется только для хранения констант.
MySQLiWorker.php
Класс-одиночка для работы с базой. В прочем это обычный одиночка — таких примеров в сети очень много.
apiBaseClass.php
Ну вот мы подошли к одному из самых важных классов системы — базовый класс для всех API в системе.
Как видно данный класс содержит в себе несколько «утилитных» методов, таких как:
конструктор в котором осуществляется соединение с базой, если текущее API собирается работать с базой;
деструктор — следит за освобождением ресурсов — разрыв установленного соединения с базой
createDefaultJson — создает дефолтный JSON для ответа метода
fillJSON — если подразумевается что запрос вернет только одну запись, то данный метод заполнит JSON для ответа данными из первой строки ответа от БД
Создадим свой API
Вот собственно и весь костяк этого API. Теперь рассмотрим как же это все использовать на примере создания первого API под названием apitest. И напишем в нем пару простых функций:
одну без параметров
одну с параметрами и их же она нам и вернет, чтобы было видно, что она их прочитала
одну которая вернет нам бинарные данные
И так создаем класс apitest.php следующего содержания
Для удобства тестирования методов, я дописываю к ним адрес по которому я могу сделать быстрый запрос для тестирования.
И так у нас три метода
helloAPI
Это простой метод без параметров. Его адрес для GET вызова www.example.com/api/?apitest.helloAPI=<>
Результатом выполнения будет вот такая страница (в браузере)
helloAPIWithParams
Этот метод принимает в параметры. Обязательным является TestParamOne, для него и сделаем проверку. Его его не передать, то будет выдан JSON с ошибкой
helloAPIResponseBinary
И последний метод helloAPIResponseBinary — вернет бинарные данные — картинку хабра о несуществующей странице (в качестве примера)
Как видно — здесь есть подмена заголовка для вывода графического контента.
Результат будет такой
Есть над чем работать
Для дальнейшего развития необходимо сделать авторизация пользователей, чтобы ввести разграничение прав на вызов запросов — какие-то оставить свободными, а какие-то только при авторизации пользователя.
Ссылки
Для тестирования выложил все файлы на github — simpleAPI
Создание RESTful API на PHP
REST или в полной форме, Representational State Transfer стало стандартной архитектурой проектирования для разработки веб-API.
REST является очень простым интерфейсом управления информацией без использования каких-то дополнительных внутренних прослоек. Каждая единица информации однозначно определяется глобальным идентификатором, таким как URL. Каждая URL в свою очередь имеет строго заданный формат.
REST использует методы HTTP-запроса, чтобы скомпоновать себя в существующую архитектуру HTTP. Эти операции состоят в следующем:
PUT- Используется для изменения существующего объекта на сервере
POST- Используется для создания нового объекта на сервере
А теперь к сути, т.е. написанию простого API, который вы можете использовать в своих проектах.
Что такое API
В примере запроса статьи API может содержать URI:
Если отправить запрос GET в этот URL, ответ может быть списком самых последних новостей, запрос PUT может добавить новость в БД.
Если запросить /article /141, то это будет определенная новость. Это примеры показывают способ взаимодействия с приложением.
Создание своего API
Что же означают строки этого файла?
В первой строке проверяется существование модуля rewrite. Если он запущен, выполняются следующие строки.
Объявляем класс, свойства и конструктор.
Объявив этот абстрактный класс, мы запретили PHP создавать конкретный экземпляр этого класса. Оттуда мы можем только использовать методы, унаследовав в другом классе. Защищенный метод может быть доступен только в самом классе и его потомках.
Создание класса API
Создаем классMyAPI который наследует абстрактный класс API.
Использование API
Теперь, если перейти по ссылке /api/v1/example то можно увидеть ответ API.