Пишем свой API для сайта с использованием Apache, PHP и MySQL
Разрабатывая проект, я столкнулся с необходимостью организации клиент-серверного взаимодействия приложений на платформах iOS и Android с моим сайтом на котором хранилась вся информация — собственно БД на mysql, картинки, файлы и другой контент.
Задачи которые нужно было решать — достаточно простые:
регистрация/авторизация пользователя;
отправка/получение неких данных (например список товаров).
И тут-то мне захотелось написать свой API для взаимодействия с серверной стороной — большей своей частью для практического интереса.
Входные данные
В своем распоряжении я имел:
Сервер — Apache, PHP 5.0, MySQL 5.0
Клиент — Android, iOS устройства, любой браузер
Я решил, что для запросов к серверу и ответов от него буду использовать JSON формат данных — за его простоту и нативную поддержку в PHP и Android. Здесь меня огорчила iOS — у нее нет нативной поддержки JSON (тут пришлось использовать стороннюю разработку).
Так же было принято решение, что запросы можно будет отсылать как через GET так и через POST запросы (здесь помог $_REQUEST в PHP). Такое решение позволило проводить тестирование API через GET запросы в любом доступном браузере.
Внешний вид запросов решено было сделать таким:
http://[адрес сервера]/[путь к папке api]/?[название_api].[название_метода]=[JSON вида ]
Путь к папке 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 для тестирования новых методов перед их включением в продакшн версию
Весь механизм выглядит следующим образом:
Мы делаем запрос на сервер — к примеру www.example.com/api будет принимать он.
0) < require_once 'apiEngine.php'; foreach ($_REQUEST as $apiFunctionName =>$apiFunctionParams) < $APIEngine=new APIEngine($apiFunctionName,$apiFunctionParams); echo $APIEngine->callApiFunction(); break; > >else< $jsonError->error='No function called'; echo json_encode($jsonError); > ?>
Первым делом устанавливаем тип контента — text/html (потом можно сменить в самих методах) и кодировку — UTF-8.
Дальше проверяем, что у нас что-то запрашивают. Если нет то выводим JSON c ошибкой.
Если есть параметры запроса, то подключаем файл движка API — apiEngine.php и создаем класс движка с переданными параметрами и делаем вызов api метода.
Выходим из цикла так как мы решили что будем обрабатывать только один вызов.
apiEngine.php
Вторым по важности является класс apiEngine — он представляет собой движок для вызова api и их методов.
//Конструктор //$apiFunctionName - название API и вызываемого метода в формате apitest_helloWorld //$apiFunctionParams - JSON параметры метода в строковом представлении function __construct($apiFunctionName, $apiFunctionParams) < $this->apiFunctionParams = stripcslashes($apiFunctionParams); //Парсим на массив из двух элементов [0] - название API, [1] - название метода в API $this->apiFunctionName = explode('_', $apiFunctionName); > //Создаем JSON ответа function createDefaultJson() < $retObject = json_decode('<>'); $response = APIConstants::$RESPONSE; $retObject->$response = json_decode('<>'); return $retObject; > //Вызов функции по переданным параметрам в конструкторе function callApiFunction() < $resultFunctionCall = $this->createDefaultJson();//Создаем JSON ответа $apiName = strtolower($this->apiFunctionName[0]);//название API проиводим к нижнему регистру if (file_exists($apiName . '.php')) < $apiClass = APIEngine::getApiEngineByName($apiName);//Получаем объект API $apiReflection = new ReflectionClass($apiName);//Через рефлексию получем информацию о классе объекта try < $functionName = $this->apiFunctionName[1];//Название метода для вызова $apiReflection->getMethod($functionName);//Провераем наличие метода $response = APIConstants::$RESPONSE; $jsonParams = json_decode($this->apiFunctionParams);//Декодируем параметры запроса в JSON объект if ($jsonParams) < if (isset($jsonParams->responseBinary))/Для возможности возврата не JSON, а бинарных данных таких как zip, png и др. контетнта return $apiClass->$functionName($jsonParams);//Вызываем метод в API >else< $resultFunctionCall->$response = $apiClass->$functionName($jsonParams);//Вызыаем метод в API который вернет JSON обект > > else < //Если ошибка декодирования JSON параметров запроса $resultFunctionCall->errno = APIConstants::$ERROR_ENGINE_PARAMS; $resultFunctionCall->error = 'Error given params'; > > catch (Exception $ex) < //Непредвиденное исключение $resultFunctionCall->error = $ex->getMessage(); > > else < //Если запрашиваемый API не найден $resultFunctionCall->errno = APIConstants::$ERROR_ENGINE_PARAMS; $resultFunctionCall->error = 'File not found'; $resultFunctionCall->REQUEST = $_REQUEST; > return json_encode($resultFunctionCall); > > ?>
apiConstants.php
Данный класс используется только для хранения констант.
MySQLiWorker.php
Класс-одиночка для работы с базой. В прочем это обычный одиночка — таких примеров в сети очень много.
//Чтобы нельзя было создать через клонирование private function __clone() < /* . */ >//Чтобы нельзя было создать через unserialize private function __wakeup() < /* . */ >//Получаем объект синглтона public static function getInstance($dbName, $dbHost, $dbUser, $dbPassword) < if (is_null(self::$instance)) < self::$instance = new MySQLiWorker(); self::$instance->dbName = $dbName; self::$instance->dbHost = $dbHost; self::$instance->dbUser = $dbUser; self::$instance->dbPassword = $dbPassword; self::$instance->openConnection(); > return self::$instance; > //Определяем типы параметров запроса к базе и возвращаем строку для привязки через ->bind function prepareParams($params) < $retSTMTString = ''; foreach ($params as $value) < if (is_int($value) || is_double($value)) < $retSTMTString.='d'; >if (is_string($value)) < $retSTMTString.='s'; >> return $retSTMTString; > //Соединяемся с базой public function openConnection() < if (is_null($this->connectLink)) < $this->connectLink = new mysqli($this->dbHost, $this->dbUser, $this->dbPassword, $this->dbName); $this->connectLink->query("SET NAMES utf8"); if (mysqli_connect_errno()) < printf("Подключение невозможно: %s\n", mysqli_connect_error()); $this->connectLink = null; > else < mysqli_report(MYSQLI_REPORT_ERROR); >> return $this->connectLink; > //Закрываем соединение с базой public function closeConnection() < if (!is_null($this->connectLink)) < $this->connectLink->close(); > > //Преобразуем ответ в ассоциативный массив public function stmt_bind_assoc(&$stmt, &$out) < $data = mysqli_stmt_result_metadata($stmt); $fields = array(); $out = array(); $fields[0] = $stmt; $count = 1; $currentTable = ''; while ($field = mysqli_fetch_field($data)) < if (strlen($currentTable) == 0) < $currentTable = $field->table; > $fields[$count] = &$out[$field->name]; $count++; > call_user_func_array('mysqli_stmt_bind_result', $fields); > > ?>
apiBaseClass.php
Ну вот мы подошли к одному из самых важных классов системы — базовый класс для всех API в системе.
mySQLWorker = MySQLiWorker::getInstance($dbName,$dbHost,$dbUser,$dbPassword); > > function __destruct() < if (isset($this->mySQLWorker))< //Если было установленно соединение с базой, $this->mySQLWorker->closeConnection(); //то закрываем его когда наш класс больше не нужен > > //Создаем дефолтный JSON для ответов function createDefaultJson() < $retObject = json_decode('<>'); return $retObject; > //Заполняем JSON объект по ответу из MySQLiWorker function fillJSON(&$jsonObject, &$stmt, &$mySQLWorker) < $row = array(); $mySQLWorker->stmt_bind_assoc($stmt, $row); while ($stmt->fetch()) < foreach ($row as $key =>$value) < $key = strtolower($key); $jsonObject->$key = $value; > break; > return $jsonObject; > > ?>
Как видно данный класс содержит в себе несколько «утилитных» методов, таких как:
конструктор в котором осуществляется соединение с базой, если текущее API собирается работать с базой;
деструктор — следит за освобождением ресурсов — разрыв установленного соединения с базой
createDefaultJson — создает дефолтный JSON для ответа метода
fillJSON — если подразумевается что запрос вернет только одну запись, то данный метод заполнит JSON для ответа данными из первой строки ответа от БД
Создадим свой API
Вот собственно и весь костяк этого API. Теперь рассмотрим как же это все использовать на примере создания первого API под названием apitest. И напишем в нем пару простых функций:
одну без параметров
одну с параметрами и их же она нам и вернет, чтобы было видно, что она их прочитала
одну которая вернет нам бинарные данные
И так создаем класс apitest.php следующего содержания
function helloAPI() < $retJSON = $this->createDefaultJson(); $retJSON->withoutParams = 'It\'s method called without parameters'; return $retJSON; > //http://www.example.com/api/?apitest.helloAPIWithParams= function helloAPIWithParams($apiMethodParams) < $retJSON = $this->createDefaultJson(); if (isset($apiMethodParams->TestParamOne))< //Все ок параметры верные, их и вернем $retJSON->retParameter=$apiMethodParams->TestParamOne; >else< $retJSON->errorno= APIConstants::$ERROR_PARAMS; > return $retJSON; > //http://www.example.com/api/?apitest.helloAPIResponseBinary= function helloAPIResponseBinary($apiMethodParams) < header('Content-type: image/png'); echo file_get_contents("http://habrahabr.ru/i/error-404-monster.jpg"); >> ?>
Для удобства тестирования методов, я дописываю к ним адрес по которому я могу сделать быстрый запрос для тестирования.
И так у нас три метода
helloAPI
function helloAPI() < $retJSON = $this->createDefaultJson(); $retJSON->withoutParams = 'It\'s method called without parameters'; return $retJSON; >
Это простой метод без параметров. Его адрес для GET вызова
helloAPIWithParams
Этот метод принимает в параметры. Обязательным является TestParamOne, для него и сделаем проверку. Его его не передать, то будет выдан JSON с ошибкой
function helloAPIWithParams($apiMethodParams) < $retJSON = $this->createDefaultJson(); if (isset($apiMethodParams->TestParamOne))< //Все ок параметры верные, их и вернем $retJSON->retParameter=$apiMethodParams->TestParamOne; >else< $retJSON->errorno= APIConstants::$ERROR_PARAMS; > return $retJSON; >

helloAPIResponseBinary
И последний метод helloAPIResponseBinary — вернет бинарные данные — картинку хабра о несуществующей странице (в качестве примера)
function helloAPIResponseBinary($apiMethodParams)< header('Content-type: image/jpeg'); echo file_get_contents("http://habrahabr.ru/i/error-404-monster.jpg"); >
Как видно — здесь есть подмена заголовка для вывода графического контента.
Результат будет такой

Есть над чем работать
Для дальнейшего развития необходимо сделать авторизация пользователей, чтобы ввести разграничение прав на вызов запросов — какие-то оставить свободными, а какие-то только при авторизации пользователя.
Ссылки
Для тестирования выложил все файлы на github — simpleAPI
Простой REST API в PHP — Пошаговое руководство
В данной статье вы узнаете, как создать простой REST API в PHP.
- 1. Обзор проекта
- 1.1 Что такое REST API?
- 1.2 Зачем нужен REST API?
- 1.3 Где используется REST API?
- 2. Файловая структура
- 3. Настройка базы данных
- 3.1 Создание таблицы категорий
- 3.2 Дамп данных для таблицы категорий
- 3.3 Создание таблицы товаров
- 3.4 Дамп данных для таблицы товаров
- 3.5 Подключение к базе данных
- 4. Получение товаров
- 4.1 Создание объекта Product
- 4.2 Создание файла для чтения товаров
- 4.3 Подключение к базе данных и таблице товаров
- 4.4 Чтение товаров из базы данных
- 4.5 Создание метода read()
- 4.6 Уведомление пользователя о том, что товары не найдены
- 5. Создание товаров
- 5.1 Создание файла 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
- 8.2 Создание метода delete()
- 9. Поиск товаров
- 9.1 Создание файла search.php
- 9.2 Создание метода search()
- 10. Пагинация товаров
- 10.1 Создание файла read_paging.php
- 10.2 Создание файла core.php
- 10.3 Создание метода readPaging()
- 10.4 Создание метода count()
- 10.5 Получение массива пагинации
- 11. Получение категорий
- 11.1 Создание класса Category
- 11.2 Создание метода readAll()
- 11.3 Создание файла read.php
1. Обзор проекта
1.1 Что такое REST API?
REST — это концепция (архитектура) для организации взаимодействия между независимыми объектами (приложениями) посредством протокола HTTP. Включает в себя набор принципов (рекомендаций) взаимодействия клиент-серверных приложений. Обычно он представлен в формате JSON.
API — интерфейс взаимодействия с каким-либо объектом (программой, приложением), включающий в себя набор правил, которые позволяют одному приложению общаться с другим. Эти «правила» могут включать в себя операции создания, чтения, обновления и удаления. Примером API может служить всем известная библиотека jQuery.
REST API позволяет вашему приложению взаимодействовать с одним или несколькими различными приложениями, используя концепции REST.

1.2 Зачем нужен REST API?
Во многих приложениях REST API необходим, потому что это самый легкий способ создания, чтения, обновления или удаления информации между различными приложениями через Интернет или протокол HTTP. Эта информация представляется пользователю в одно мгновение, особенно если вы используете JavaScript для отображения данных на веб-странице.
1.3 Где используется REST API?
REST API может использоваться любым приложением, которое может подключаться к Интернету. Если данные из приложения могут быть созданы, прочитаны, обновлены или удалены с помощью другого приложения, это обычно означает, что используется REST API.
2. Файловая структура
- api/
- config/
- core.php
- database.php
- product.php
- category.php
- create.php/
- delete.php/
- read.php/
- read_paging.php/
- read_one.php/
- update.php/
- search.php/
- read.php
- utilities.php
3. Настройка базы данных
Используя PhpMyAdmin , создайте новую базу данных api_db . После этого выполните следующие SQL-запросы, чтобы создать новые таблицы с образцами данных.
3.1 Создание таблицы категорий
CREATE TABLE IF NOT EXISTS `categories` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(256) NOT NULL, `description` text NOT NULL, `created` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=19 ;3.2 Дамп данных для таблицы категорий
INSERT INTO `categories` (`id`, `name`, `description`, `created`, `modified`) VALUES (1, "Fashion", "Category for anything related to fashion.", "2014-06-01 00:35:07", "2014-05-30 17:34:33"), (2, "Electronics", "Gadgets, drones and more.", "2014-06-01 00:35:07", "2014-05-30 17:34:33"), (3, "Motors", "Motor sports and more", "2014-06-01 00:35:07", "2014-05-30 17:34:54"), (5, "Movies", "Movie products.", "2019-05-20 10:22:05", "2019-08-20 10:30:15"), (6, "Books", "Kindle books, audio books and more.", "2018-03-14 08:05:25", "2019-05-20 11:29:11"), (13, "Sports", "Drop into new winter gear.", "2016-01-09 02:24:24", "2016-01-09 01:24:24");3.3 Создание таблицы товаров
CREATE TABLE IF NOT EXISTS `products` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `description` text NOT NULL, `price` decimal(10,0) NOT NULL, `category_id` int(11) NOT NULL, `created` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=65 ;3.4 Дамп данных для таблицы товаров
INSERT INTO `products` (`id`, `name`, `description`, `price`, `category_id`, `created`, `modified`) VALUES (1, "LG P880 4X HD", "My first awesome phone!", "336", 3, "2014-06-01 01:12:26", "2014-05-31 17:12:26"), (2, "Google Nexus 4", "The most awesome phone of 2013!", "299", 2, "2014-06-01 01:12:26", "2014-05-31 17:12:26"), (3, "Samsung Galaxy S4", "How about no?", "600", 3, "2014-06-01 01:12:26", "2014-05-31 17:12:26"), (6, "Bench Shirt", "The best shirt!", "29", 1, "2014-06-01 01:12:26", "2014-05-31 02:12:21"), (7, "Lenovo Laptop", "My business partner.", "399", 2, "2014-06-01 01:13:45", "2014-05-31 02:13:39"), (8, "Samsung Galaxy Tab 10.1", "Good tablet.", "259", 2, "2014-06-01 01:14:13", "2014-05-31 02:14:08"), (9, "Spalding Watch", "My sports watch.", "199", 1, "2014-06-01 01:18:36", "2014-05-31 02:18:31"), (10, "Sony Smart Watch", "The coolest smart watch!", "300", 2, "2014-06-06 17:10:01", "2014-06-05 18:09:51"), (11, "Huawei Y300", "For testing purposes.", "100", 2, "2014-06-06 17:11:04", "2014-06-05 18:10:54"), (12, "Abercrombie Lake Arnold Shirt", "Perfect as gift!", "60", 1, "2014-06-06 17:12:21", "2014-06-05 18:12:11"), (13, "Abercrombie Allen Brook Shirt", "Cool red shirt!", "70", 1, "2014-06-06 17:12:59", "2014-06-05 18:12:49"), (26, "Another product", "Awesome product!", "555", 2, "2014-11-22 19:07:34", "2014-11-21 20:07:34"), (28, "Wallet", "You can absolutely use this one!", "799", 6, "2014-12-04 21:12:03", "2014-12-03 22:12:03"), (31, "Amanda Waller Shirt", "New awesome shirt!", "333", 1, "2014-12-13 00:52:54", "2014-12-12 01:52:54"), (42, "Nike Shoes for Men", "Nike Shoes", "12999", 3, "2015-12-12 06:47:08", "2015-12-12 05:47:08"), (48, "Bristol Shoes", "Awesome shoes.", "999", 5, "2016-01-08 06:36:37", "2016-01-08 05:36:37"), (60, "Rolex Watch", "Luxury watch.", "25000", 1, "2016-01-11 15:46:02", "2016-01-11 14:46:02");3.5 Подключение к базе данных
Приведенный ниже код показывает учетные данные базы данных и метод для получения подключения к базе данных с помощью PDO .
Создайте папку api и откройте её. Создайте папку config и в ней создайте файл database.php со следующим кодом.
conn = null; try < $this->conn = new PDO("mysql:host ;dbname set names utf8"); > catch (PDOException $exception) < echo "Ошибка подключения: " . $exception->getMessage(); > return $this->conn; > >4. Получение товаров
4.1 Создание объекта Product
Код ниже содержит класс с именем Product и несколько свойств. Также показан метод конструктора, который принимает соединение с базой данных.
Мы будем использовать этот класс для чтения данных из базы. Откройте папку api . Создайте папку objects . Откройте папку её и создайте файл product.php . Поместите в него следующий код.
conn = $db; > // здесь будет метод read() >4.2 Создание файла для чтения товаров
Код ниже содержит заголовки о том, кто может читать этот файл и какой тип содержимого он будет возвращать.
В данном случае наш файл read.php может быть прочитан кем угодно (звездочка * означает все) и вернет данные в формате JSON.
Откройте папку api . Создайте в ней папку product . Откройте её и создайте файл read.php со следующим кодом.
4.3 Подключение к базе данных и таблице товаров
В приведенном ниже коде мы подключаем файлы database.php и product.php . Это файлы, которые мы создали ранее.
Нам нужно использовать метод getConnection() класса Database для получения соединения с базой данных. Мы передаем это подключение классу Product .
Замените комментарий // подключение к базе данных будет здесь в файле read.php следующим кодом.
// подключение базы данных и файл, содержащий объекты include_once "../config/database.php"; include_once "../objects/product.php"; // получаем соединение с базой данных $database = new Database(); $db = $database->getConnection(); // инициализируем объект $product = new Product($db); // чтение товаров будет здесь4.4 Чтение товаров из базы данных
В приведенном ниже коде мы используем метод read() класса Product для получения данных из базы. Через переменную $num мы проверяем, найдены ли записи.
Если найдены записи, мы перебираем их с помощью цикла while , и добавляем каждую запись в массив $products_arr , устанавливаем код ответа 200 OK и показываем его пользователю в формате JSON.
Замените комментарий // чтение товаров будет здесь в файле read.php следующим кодом.
// запрашиваем товары $stmt = $product->read(); $num = $stmt->rowCount(); // проверка, найдено ли больше 0 записей if ($num > 0) < // массив товаров $products_arr = array(); $products_arr["records"] = array(); // получаем содержимое нашей таблицы // fetch() быстрее, чем fetchAll() while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) < // извлекаем строку extract($row); $product_item = array( "id" =>$id, "name" => $name, "description" => html_entity_decode($description), "price" => $price, "category_id" => $category_id, "category_name" => $category_name ); array_push($products_arr["records"], $product_item); > // устанавливаем код ответа - 200 OK http_response_code(200); // выводим данные о товаре в формате JSON echo json_encode($products_arr); > // "товары не найдены" будет здесь4.5 Создание метода read()
Мы использовали метод read() в предыдущем разделе, но он пока ещё не существует в классе Product . Нам нужно добавить этот метод. С помощью кода ниже, мы делаем запрос для получения записей из базы данных.
Откройте папку objects . Откройте файл product.php . Поместите следующий код в класс Product перед последней закрывающей фигурной скобкой вместо комментария // здесь будет метод read() .
// метод для получения товаров function read() < // выбираем все записи $query = "SELECT c.name as category_name, p.id, p.name, p.description, p.price, p.category_id, p.created FROM " . $this->table_name . " p LEFT JOIN categories c ON p.category_id = c.id ORDER BY p.created DESC"; // подготовка запроса $stmt = $this->conn->prepare($query); // выполняем запрос $stmt->execute(); return $stmt; >4.6 Уведомление пользователя о том, что товары не найдены
Если переменная $num имеет нулевое или отрицательное значение, это означает, что из базы данных не возвращено никаких записей. Мы должны сообщить пользователю об этом.
В приведенном ниже коде мы устанавливаем код ответа 404 — Не найдено и сообщение, что Товары не найдены .
Замените комментарий // «товары не найдены» будет здесь в файле read.php следующим кодом.
else < // установим код ответа - 404 Не найдено http_response_code(404); // сообщаем пользователю, что товары не найдены echo json_encode(array("message" =>"Товары не найдены."), JSON_UNESCAPED_UNICODE); >5. Создание товаров
5.1 Создание файла create.php
Откройте папку product и создайте в ней файл create.php со следующим содержимым.
getConnection(); $product = new Product($db); // получаем отправленные данные $data = json_decode(file_get_contents("php://input")); // убеждаемся, что данные не пусты if ( !empty($data->name) && !empty($data->price) && !empty($data->description) && !empty($data->category_id) ) < // устанавливаем значения свойств товара $product->name = $data->name; $product->price = $data->price; $product->description = $data->description; $product->category_id = $data->category_id; $product->created = date("Y-m-d H:i:s"); // создание товара if ($product->create()) < // установим код ответа - 201 создано http_response_code(201); // сообщим пользователю echo json_encode(array("message" =>"Товар был создан."), JSON_UNESCAPED_UNICODE); > // если не удается создать товар, сообщим пользователю else < // установим код ответа - 503 сервис недоступен http_response_code(503); // сообщим пользователю echo json_encode(array("message" =>"Невозможно создать товар."), JSON_UNESCAPED_UNICODE); > > // сообщим пользователю что данные неполные else < // установим код ответа - 400 неверный запрос http_response_code(400); // сообщим пользователю echo json_encode(array("message" =>"Невозможно создать товар. Данные неполные."), JSON_UNESCAPED_UNICODE); >5.2 Создание метода create()
Откройте папку objects . Откройте файл product.php и добавьте следующий код внутри класса Product (objects / product.php).
// метод для создания товаров function create() < // запрос для вставки (создания) записей $query = "INSERT INTO " . $this->table_name . " SET name=:name, price=:price, description=:description, category_id=:category_id, created=:created"; // подготовка запроса $stmt = $this->conn->prepare($query); // очистка $this->name = htmlspecialchars(strip_tags($this->name)); $this->price = htmlspecialchars(strip_tags($this->price)); $this->description = htmlspecialchars(strip_tags($this->description)); $this->category_id = htmlspecialchars(strip_tags($this->category_id)); $this->created = htmlspecialchars(strip_tags($this->created)); // привязка значений $stmt->bindParam(":name", $this->name); $stmt->bindParam(":price", $this->price); $stmt->bindParam(":description", $this->description); $stmt->bindParam(":category_id", $this->category_id); $stmt->bindParam(":created", $this->created); // выполняем запрос if ($stmt->execute()) < return true; >return false; >6. Получение одного товара
6.1 Создание файла read_one.php
Откройте папку product , создайте в ней файл read_one.php со следующим содержимым.
getConnection(); // подготовка объекта $product = new Product($db); // установим свойство ID записи для чтения $product->id = isset($_GET["id"]) ? $_GET["id"] : die(); // получим детали товара $product->readOne(); if ($product->name != null) < // создание массива $product_arr = array( "id" =>$product->id, "name" => $product->name, "description" => $product->description, "price" => $product->price, "category_id" => $product->category_id, "category_name" => $product->category_name ); // код ответа - 200 OK http_response_code(200); // вывод в формате json echo json_encode($product_arr); > else < // код ответа - 404 Не найдено http_response_code(404); // сообщим пользователю, что такой товар не существует echo json_encode(array("message" =>"Товар не существует"), JSON_UNESCAPED_UNICODE); >6.2 Создание метода readOne()
Откройте папку objects . Откройте файл product.php и добавьте следующий код внутри класса Product .
// метод для получения конкретного товара по ID function readOne() < // запрос для чтения одной записи (товара) $query = "SELECT c.name as category_name, p.id, p.name, p.description, p.price, p.category_id, p.created FROM " . $this->table_name . " p LEFT JOIN categories c ON p.category_id = c.id WHERE p.id = ? LIMIT 0,1"; // подготовка запроса $stmt = $this->conn->prepare($query); // привязываем id товара, который будет получен $stmt->bindParam(1, $this->id); // выполняем запрос $stmt->execute(); // получаем извлеченную строку $row = $stmt->fetch(PDO::FETCH_ASSOC); // установим значения свойств объекта $this->name = $row["name"]; $this->price = $row["price"]; $this->description = $row["description"]; $this->category_id = $row["category_id"]; $this->category_name = $row["category_name"]; >7. Обновление товара
7.1 Создание файла update.php
Откройте папку product , создайте в ней файл update.php и поместите в него следующий код.
getConnection(); // подготовка объекта $product = new Product($db); // получаем id товара для редактирования $data = json_decode(file_get_contents("php://input")); // установим id свойства товара для редактирования $product->id = $data->id; // установим значения свойств товара $product->name = $data->name; $product->price = $data->price; $product->description = $data->description; $product->category_id = $data->category_id; // обновление товара if ($product->update()) < // установим код ответа - 200 ok http_response_code(200); // сообщим пользователю echo json_encode(array("message" =>"Товар был обновлён"), JSON_UNESCAPED_UNICODE); > // если не удается обновить товар, сообщим пользователю else < // код ответа - 503 Сервис не доступен http_response_code(503); // сообщение пользователю echo json_encode(array("message" =>"Невозможно обновить товар"), JSON_UNESCAPED_UNICODE); >7.2 Создание метода update()
В папке objects откройте файл product.php и добавьте новый метод update() внутри класса Product .
// метод для обновления товара function update() < // запрос для обновления записи (товара) $query = "UPDATE " . $this->table_name . " SET name = :name, price = :price, description = :description, category_id = :category_id WHERE // подготовка запроса $stmt = $this->conn->prepare($query); // очистка $this->name = htmlspecialchars(strip_tags($this->name)); $this->price = htmlspecialchars(strip_tags($this->price)); $this->description = htmlspecialchars(strip_tags($this->description)); $this->category_id = htmlspecialchars(strip_tags($this->category_id)); $this->id = htmlspecialchars(strip_tags($this->id)); // привязываем значения $stmt->bindParam(":name", $this->name); $stmt->bindParam(":price", $this->price); $stmt->bindParam(":description", $this->description); $stmt->bindParam(":category_id", $this->category_id); $stmt->bindParam(":id", $this->id); // выполняем запрос if ($stmt->execute()) < return true; >return false; >8. Удаление товара
8.1 Создание файла delete.php
Откройте папку product и создайте файл delete.php со следующим содержимым.
getConnection(); // подготовка объекта $product = new Product($db); // получаем id товара $data = json_decode(file_get_contents("php://input")); // установим id товара для удаления $product->id = $data->id; // удаление товара if ($product->delete()) < // код ответа - 200 ok http_response_code(200); // сообщение пользователю echo json_encode(array("message" =>"Товар был удалён"), JSON_UNESCAPED_UNICODE); > // если не удается удалить товар else < // код ответа - 503 Сервис не доступен http_response_code(503); // сообщим об этом пользователю echo json_encode(array("message" =>"Не удалось удалить товар")); >8.2 Создание метода delete()
В папке objects откройте файл product.php и добавьте новый метод в класс Product .
// метод для удаления товара function delete() < // запрос для удаления записи (товара) $query = "DELETE FROM " . $this->table_name . " WHERE // подготовка запроса $stmt = $this->conn->prepare($query); // очистка $this->id = htmlspecialchars(strip_tags($this->id)); // привязываем id записи для удаления $stmt->bindParam(1, $this->id); // выполняем запрос if ($stmt->execute()) < return true; >return false; >9. Поиск товаров
Теперь реализуем поиск записей в базе данных, в нашем случае товаров.
9.1 Создание файла search.php
В папке product создайте файл search.php со следующим кодом.
getConnection(); // инициализируем объект $product = new Product($db); // получаем ключевые слова $keywords = isset($_GET["s"]) ? $_GET["s"] : ""; // запрос товаров $stmt = $product->search($keywords); $num = $stmt->rowCount(); // проверяем, найдено ли больше 0 записей if ($num > 0) < // массив товаров $products_arr = array(); $products_arr["records"] = array(); // получаем содержимое нашей таблицы // fetch() быстрее чем fetchAll() while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) < // извлечём строку extract($row); $product_item = array( "id" =>$id, "name" => $name, "description" => html_entity_decode($description), "price" => $price, "category_id" => $category_id, "category_name" => $category_name ); array_push($products_arr["records"], $product_item); > // код ответа - 200 OK http_response_code(200); // покажем товары echo json_encode($products_arr); > else < // код ответа - 404 Ничего не найдено http_response_code(404); // скажем пользователю, что товары не найдены echo json_encode(array("message" =>"Товары не найдены."), JSON_UNESCAPED_UNICODE); >9.2 Создание метода search()
В папке objects откройте product.php и добавьте метод search() .
// метод для поиска товаров function search($keywords) < // поиск записей (товаров) по "названию товара", "описанию товара", "названию категории" $query = "SELECT c.name as category_name, p.id, p.name, p.description, p.price, p.category_id, p.created FROM " . $this->table_name . " p LEFT JOIN categories c ON p.category_id = c.id WHERE p.name LIKE ? OR p.description LIKE ? OR c.name LIKE ? ORDER BY p.created DESC"; // подготовка запроса $stmt = $this->conn->prepare($query); // очистка $keywords = htmlspecialchars(strip_tags($keywords)); $keywords = "%%"; // привязка $stmt->bindParam(1, $keywords); $stmt->bindParam(2, $keywords); $stmt->bindParam(3, $keywords); // выполняем запрос $stmt->execute(); return $stmt; >10. Пагинация товаров
10.1 Создание файла read_paging.php
В папке product создайте файл read_paging.php со следующим кодом.
getConnection(); // инициализация объекта $product = new Product($db); // запрос товаров $stmt = $product->readPaging($from_record_num, $records_per_page); $num = $stmt->rowCount(); // если больше 0 записей if ($num > 0) < // массив товаров $products_arr = array(); $products_arr["records"] = array(); $products_arr["paging"] = array(); // получаем содержимое нашей таблицы while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) < // извлечение строки extract($row); $product_item = array( "id" =>$id, "name" => $name, "description" => html_entity_decode($description), "price" => $price, "category_id" => $category_id, "category_name" => $category_name ); array_push($products_arr["records"], $product_item); > // подключим пагинацию $total_rows = $product->count(); $page_url = "product/read_paging.php?"; $paging = $utilities->getPaging($page, $total_rows, $records_per_page, $page_url); $products_arr["paging"] = $paging; // установим код ответа - 200 OK http_response_code(200); // вывод в json-формате echo json_encode($products_arr); > else < // код ответа - 404 Ничего не найдено http_response_code(404); // сообщим пользователю, что товаров не существует echo json_encode(array("message" =>"Товары не найдены"), JSON_UNESCAPED_UNICODE); >10.2 Создание файла core.php
Этот файл содержит нашу базовую конфигурацию, такую как базовый URL и переменные пагинации.
Откройте папку config и создайте в ней файл core.php со следующим содержимым.
10.3 Создание метода readPaging()
В папке objects откройте файл product.php и добавьте метод readPaging() . Этот метод вернет список записей, ограниченный тем, что мы установили в $records_per_page файла core.php .
// получение товаров с пагинацией public function readPaging($from_record_num, $records_per_page) < // выборка $query = "SELECT c.name as category_name, p.id, p.name, p.description, p.price, p.category_id, p.created FROM " . $this->table_name . " p LEFT JOIN categories c ON p.category_id = c.id ORDER BY p.created DESC LIMIT ?, ?"; // подготовка запроса $stmt = $this->conn->prepare($query); // свяжем значения переменных $stmt->bindParam(1, $from_record_num, PDO::PARAM_INT); $stmt->bindParam(2, $records_per_page, PDO::PARAM_INT); // выполняем запрос $stmt->execute(); // вернём значения из базы данных return $stmt; >10.4 Создание метода count()
Так же в классе Product (файл product.php) добавьте метод count() для подсчёта количества товаров.
// данный метод возвращает кол-во товаров public function count() < $query = "SELECT COUNT(*) as total_rows FROM " . $this->table_name . ""; $stmt = $this->conn->prepare($query); $stmt->execute(); $row = $stmt->fetch(PDO::FETCH_ASSOC); return $row["total_rows"]; >10.5 Получение массива пагинации
В корне создайте папку shared , в ней файл utilities.php со следующим кодом.
1 ? "page=1" : ""; // подсчёт всех товаров в базе данных для подсчета общего количества страниц $total_pages = ceil($total_rows / $records_per_page); // диапазон ссылок для показа $range = 2; // отображать диапазон ссылок вокруг текущей страницы $initial_num = $page - $range; $condition_limit_num = ($page + $range) + 1; $paging_arr["pages"] = array(); $page_count = 0; for ($x = $initial_num; $x < $condition_limit_num; $x++) < // убедимся, что $x >0 И $x 0) && ($x <= $total_pages)) < $paging_arr["pages"][$page_count]["page"] = $x; $paging_arr["pages"][$page_count]["url"] = "page="; $paging_arr["pages"][$page_count]["current_page"] = $x == $page ? "yes" : "no"; $page_count++; > > // кнопка для последней страницы $paging_arr["last"] = $page < $total_pages ? "page=" : ""; // формат json returnjson_encode($paging_arr); > >11. Получение категорий
11.1 Создание класса Category
Откройте папку objects и создайте новый файл category.php со следующим кодом.
conn = $db; > // здесь будет метод для получение всех категорий товаров >11.2 Создание метода readAll()
С помощью данного метода мы получим все категории товаров из базы данных. замените комментарий // здесь будет метод для получение всех категорий товаров следующим кодом:
// метод для получения всех категорий товаровpublic function readAll() < $query = "SELECT id, name, description FROM " . $this->table_name . " ORDER BY name"; $stmt = $this->conn->prepare($query); $stmt->execute(); return $stmt; >11.3 Создание файла read.php
Создайте новую папку category в корне, и в ней файл read.php со следующим кодом.
getConnection(); // инициализация объекта $category = new Category($db); // получаем категории $stmt = $category->readAll(); $num = $stmt->rowCount(); // проверяем, найдено ли больше 0 записей if ($num > 0) < // массив для записей $categories_arr = array(); $categories_arr["records"] = array(); // получим содержимое нашей таблицы while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) < // извлекаем строку extract($row); $category_item = array( "id" =>$id, "name" => $name, "description" => html_entity_decode($description) ); array_push($categories_arr["records"], $category_item); > // код ответа - 200 OK http_response_code(200); // покажем данные категорий в формате json echo json_encode($categories_arr); > else < // код ответа - 404 Ничего не найдено http_response_code(404); // сообщим пользователю, что категории не найдены echo json_encode(array("message" =>"Категории не найдены"), JSON_UNESCAPED_UNICODE); >API готов к использованию!
Frontend часть данного приложения (продолжение) — jQuery + AJAX + JSON.
Если вам понравилась данная статья, рекомендую к прочтению создание регистрации и авторизации в php с использованием JWT.
Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.
Поделиться с друзьями:
Статьи из данной категории:
- YouTube API Key (Получение + Пример)
- Переменные в цикле php
- Сортировка по произвольному полю (WordPress)
- WordPress Пагинация без Плагина
- PHP ООП MySQL — Пошаговое руководство
- WordPress: Поиск по Сайту (без плагинов)
Комментарии ( 29 )
Константин
14/02/2020, 17:48Вот это статься, отличное руководство как создать REST, единственное как новичку трудно понять а зачем это все..честно говоря уже 3 дня перекапываю инет в поисках нормальной статьи что такое rest API и нафига оно нужно, одна проблема где то пишут что это такое и какие у него преимущества поверхностно, типа ну так проще жить и бла бла бла, в других сразу приходят к суровой реализации не объясняя что и за чем делается. Ваша пока лучшая в этом плане, хотя бы понятно что делается, правда не понятно что в конце должно получиться. и почему это делается именно так а не иначе. Например простой вопрос, зачем пишутся header, почти в каждом файле. Ответ в инете адекватный и простыми словами задолбаешься искать.
Only to top
15/02/2020, 21:57Рад, что вам понравилась статья, Константин. В header мы записываем необходимую информацию для настройки взаимодействия между клиентом и сервером. Примеры используемых заголовков: Access-Control-Allow-Origin — кем может быть прочитан файл. (* — доступ открыт для всех сайтов). Content-Type — ожидаемый формат данных. Access-Control-Allow-Methods — какие методы могут использоваться во время запроса (POST, GET, PUT и т.п.). Access-Control-Max-Age — кэширование предзапроса в секундах (-1 — отмена кэширования, предзапрос будет отправляться перед каждым запросом). Access-Control-Allow-Headers — указываем список HTTP заголовков, которые могут быть использованы в запросе.
21/01/2023, 18:01
Ну я подумал так и понял что ох.. какое хорошее тут разъяснение, мне много стало ясно
20/02/2020, 12:22Такой вопрос, в принципе понятно, но как вся эта информация передаётся фронту или точнее, как фронт получает все эти данные для дальнейшей работы?
Only to top
20/02/2020, 19:06Тимур, предыдущая статья является как раз фронтом — jQuery, AJAX, JSON. Текущая статья + предыдущая = полноценное веб-приложение.
25/02/2020, 06:30
Огромное спасибо, действительно очень полезные статьи)
19/03/2020, 16:03Спасибо за статью, очень хорошо всё описано. А что если добавить всё это дело в Composer? Т.е. использовать стандарт PSR4 для структуры проекта?
20/04/2020, 20:31
Хорошая подача материала, спасибо вам. Появился вопрос: Какой паттерн программирования используется в данном примере?
21/05/2020, 13:19
Спасибо за статью! Действительно, всё очень хорошо разжёвано!
Билли Херрингтон
16/06/2020, 18:16
А почему все через POST? Как же PUT и DELETE?
26/07/2020, 17:35
Скажите для чего вы используете http_response_code ?
16/08/2020, 17:37Спасибо автору, выложено грамотно. Но для начинаюших не понятно как все это работает. Автор показал бы несколько примеров. Запрос — ответ, запрос — ответ..
25/11/2020, 04:46
В read.php в этих строчках ругается:$product_item = array( "id" => $id, "name" => $name, "description" =>_entity_decode($description), "price" => $price, "category_id" => $category_id, "category_name" => $category_name );Что якобы нету никакого $id или $name.
09/12/2020, 18:28
Значит косяк с твоей стороны где-то.
Я всё запустил включая и фронт — всё работает.
23/07/2023, 12:55
Это из-за extract(): https://www.w3schools.com/php/func_array_extract.asp
21/01/2021, 11:43Добрый день. Правильно я понимаю, подобное api также служит для crud для таких frontend framework как vue.js или react, чтобы можно было взаимодействовать с данными с сервера, допусти через axios vuex ?
Only to top
21/01/2021, 13:38Здравствуйте, Юрий. Всё верно. Так же подобный api можно использовать где угодно, хоть на самописном сайте с нативным php.
04/03/2021, 19:51
Извините за тупой вопрос, но как передаются аргументы в url? То есть, например, когда мы обращаемся к файлу create.php, как надо дальше писать в url?
Only to top
04/03/2021, 20:18
Например, так, Владимир:
1) в app/products/products.js добавьте дата-атрибут с нужным значением;
2) а в appproductscreate-product.js получите его при клике на кнопку, после нажатия на которую мы показываем форму создания товара.04/03/2021, 20:28
А если я без фронта делаю? Пишу приложение на iOS, и мне надо получать данные в json(с этим понятно), а вот как отправить я не понимаю. вот пишу http://my_ip/api/product/create.php и что дальше писать?
Only to top
04/03/2021, 20:36Я наверно не совсем понимаю в чём у вас проблема. просто добавляйте их в URL: http://my_ip/api/product/create.php?arg=value&arg2=value2
04/03/2021, 20:45
Спасибо! то что надо!
11/05/2021, 23:12Здравствуйте! В постмане запускаю http://192.168.64.3/api/product/delete.php?id=1 удаление. И в терминале вижу:
Notice: Trying to get property 'id' of non-object in /opt/lampp/htdocs/api/product/delete.php on line 24
Сервер локальный Xampp, но когда захожу в phpMyAdmin он по прежнему в базе данных. Подскажите пожалуйста куда копать. Захожу под root, привилегии все открыты.
20/02/2022, 16:19
Приветствую, Максим. Во-первых, может и глупо звучит, но всё же, в БД у имеющейся записи поле id равно 1 или там другое значение? Во-вторых, и наиболее вероятно, если речь про эту строку кода:
$data = json_decode(file_get_contents("php://input"));То здесь предполагается получение входных данных в JSON формате, а у Вас просто передан параметр Попробуйте передать запрос на удаление в JSON формате.
30/06/2021, 15:21
Благодарю за труд!
16/07/2021, 09:45Первый раз делал REST, описано подробно и понятно, спасибо огромное, запустился с первого раза! Если можно вопрос, может Вы подскажете. Как сделать чтобы можно было менять адрес сервера, так как структуры данных одинаковые, только серверы разные, чтобы не плодить REST-ы? Чтобы был один REST и он обращался с указанному серверу с данным. Спасибо Вам.
27/11/2021, 19:13
Огромное спасибо Автору за труд. Всё четко и понятно изложено, красиво оформлено ❤️, а эти сердечки и лапки в заголовке. ну правда, не хочется покидать страницу :))) Спасибо за прекрасный и очень полезный материал!
19/03/2023, 04:17
Какое же это для меня спасение, я столько инфы видел и эта просто самая годная, легкая и простая в освоении!
03/08/2023, 08:06
Отличная статья как раз разбирался как сделать подобное приложение. Жаль мне она не много не подходит т.к. у меня база данных находиться на PostgreSQL. Кстати не подскажите, что нужно поменять чтобы, это работало и с PostgreSQL. Я так думаю, что вот здесь
public function getConnection() < $this->conn = null; try < $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password); $this->conn->exec("set names utf8"); > catch (PDOException $exception) < echo "Ошибка подключения: " . $exception->getMessage(); > return $this->conn; > >На что-то вроде этого
public function getConnection() < password=$password"; $this->conn = null; try < $this->conn = new PDO("pgsql:host=$host; port=5432; dbname=$db; user=$username; password=$password"); $this->conn->exec("set names utf8"); > catch (PDOException $exception) < echo "Ошибка подключения: " . $exception->getMessage(); > return $this->conn; >Но это не правильно, я получаю ошибку
SQLSTATE[08006] [7] could not translate host name "port=5432" to address: Name or service not knownКак создать свой API на сайте

Не так давно один из моих посетителей мне задал вопрос по e-mail: «Как создать свой API на сайте?«. Я решил, что это будет весьма полезно другим пользователям, тем более, что на кажущуюся сложность процесса, всё очень и очень просто. Необходимо лишь обладать самыми элементарными знаниями PHP.
Если Вы вдруг не понимаете, о чём идёт речь, то прочитайте сначала статью: что такое API. Идём дальше. Давайте разберём, а для каких сайтов нужен вообще API:
- Социальные сети (Facebook и другие). Здесь требуется API для получения информации о различных данных пользователя: его друзьях, личных сообщениях и прочей информации.
- Почтовые сервисы (например, mail.ru). В первую очередь, для получения писем. Иногда для отправки.
- Различные сервисы для создания Интернет-магазинов. Например, получить список новых заказов или список всех товаров в заданной категории.
- И много-много других сайтов.
Первое, что необходимо усвоить — это то, что API нужен далеко не каждому сайту (даже если он принадлежит одной из вышеуказанных групп).
Если же Вы считаете, что API на Вашем сайте необходим, то давайте разберём пример того, как он создаётся. Пусть у нас будет такая задача: есть ЭПС (как, например, WebMoney). И мы хотим, чтобы пользователь мог из своего кода, пользуясь нашим API, узнать свой баланс на счёте.
Создадим файл (например, api.php), который у нас будет принимать GET-запросы от пользователей на получение различной информации. Напишем в этом обработчике такой код:
if ($_GET[‘action’] == «getbalance») $balance;
//Узнаём из базы данных баланс аккаунта и записываем в переменную balance
echo $balance;
>
?>Теперь разработчики API должны дать информацию пользователям о том, как надо отправлять запрос, чтобы пользователь мог узнать свой баланс на аккаунте:
Этот запрос пользователи формируют в своих скриптах (например, через cURL). Параметр key — это уникальный ключ каждого пользователя. И ответом этого запроса будет число, отвечающее за баланс пользователя. Аналогично создаются и все другие возможности API. Можно добавлять другие различные параметры: например, получить список операций пополнения счёта с одной даты по другую. Желательно, сами списки возвращать в формате JSON.
Вот так легко и просто создаётся API для сайта. Безусловно, нужен он Вам или нет — решать только Вам, а всю самую необходимую информацию я Вам только что дал.


Создано 02.07.2011 14:21:21
- Михаил Русаков
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновленияЕсли у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
- Кнопка:
Она выглядит вот так: - Текстовая ссылка:
Она выглядит вот так: Как создать свой сайт - BB-код ссылки для форумов (например, можете поставить её в подписи):
Комментарии ( 20 ):
sync.o 02.07.2011 22:02:30
что такое API — ссылка не та)
Admin 02.07.2011 22:05:10
Большое спасибо! Уже исправлено.
Создание REST API с аутентификацией

Ищете как создать RESTful API в Laravel? Если да, то я расскажу вам всё поэтапно, как создать полноценный API с аутентификацией с использованием Laravel Passport. API также известен как веб-служба.
На сегодняшний день, как мы знаем, Laravel является самым популярным фреймворком по причине своей безопасности. Поэтому многие разработчики выбирают его для разработки API мобильных приложений. Да, веб-службы очень важны при создании веб- и мобильных приложений, потому что вы можете создать одну базу данных для всех версий и работать с одинаковыми данными.
Если вы не знакомы с Laravel или не знаете, как начать создание API, не беспокойтесь, в этом уроке я шаг за шагом всё объясню. Вам просто нужно выполнить несколько этапов, чтобы получить API для регистрации, входа и работы с товарами (добавление, обновление, удаление).
Шаг 1: Установка Laravel
Поскольку это пошаговый урок, прямо с нуля, то нам нужно сначала установить Laravel. Откройте командную строку и выполните команду:
composer create-project --prefer-dist laravel/laravel blog
Шаг 2: Установка Passport
Устанавливаем Passport с помощью менеджера пакетов Composer, запустите команду:
composer require laravel/passport
После успешной установки пакета нам необходимо получить миграции для создания новых таблиц в нашей базе данных. Запускайте команду:
php artisan migrate
Далее, для получения токенов безопасности, нам нужно запустить команду:
php artisan passport:install
Шаг 3: Настройка паспорта
В этом шаге мы должны провести настройку в трех местах: в модели, в сервис-провайдере и в файле конфигурации.
В модели мы добавим класс HasApiTokens,
В AuthServiceProvider мы добавим Passport::routes(),
В файле auth.php мы добавим настройки аутентификации api.
app/User.php
app/Providers/AuthServiceProvider.php
'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() < $this->registerPolicies(); Passport::routes(); > >
config/auth.php
return [ . 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ], . ]
Шаг 4: Добавляем таблицу товаров и Модель
Теперь нам нужно создать миграцию для таблицы товаров:
php artisan make:migration create_products_table
После выполнения этой команды вы найдете новый файл в папке database/migrations. Вам нужно вставить в него приведенный ниже код для создания таблицы товаров.
increments('id'); $table->string('name'); $table->text('detail'); $table->timestamps(); >); > /** * Reverse the migrations. * * @return void */ public function down() < Schema::dropIfExists('products'); >>Теперь нужно запустить миграцию:
php artisan migrate
Таким образом мы создали таблицу «products». Теперь нужно сделать модель Product — создайте файл Product.php в папке app и поместите в него приведенный ниже код:
Шаг 5. Создание маршрутов API
На этом этапе мы создадим маршруты API. Laravel предлагает для записи маршрутов веб-сервисов файл api.php. Давайте добавим новый маршрут к этому файлу.
group( function () < Route::resource('products', 'API\ProductController'); >);Шаг 6: Создание файлов Контроллера
В этом шаге мы будем создавать новые контроллеры — BaseController, ProductController и RegisterController. Для них я создал новую папку «API» в папке контроллеров.
app/Http/Controllers/API/BaseController.php
true, 'data' => $result, 'message' => $message, ]; return response()->json($response, 200); > /** * return error response. * * @return \Illuminate\Http\Response */ public function sendError($error, $errorMessages = [], $code = 404) < $response = [ 'success' =>false, 'message' => $error, ]; if(!empty($errorMessages)) < $response['data'] = $errorMessages; >return response()->json($response, $code); > >
app/Http/Controllers/API/ProductController.php
sendResponse($products->toArray(), 'Products retrieved successfully.'); > /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) < $input = $request->all(); $validator = Validator::make($input, [ 'name' => 'required', 'detail' => 'required' ]); if($validator->fails())< return $this->sendError('Validation Error.', $validator->errors()); > $product = Product::create($input); return $this->sendResponse($product->toArray(), 'Product created successfully.'); > /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) < $product = Product::find($id); if (is_null($product)) < return $this->sendError('Product not found.'); > return $this->sendResponse($product->toArray(), 'Product retrieved successfully.'); > /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, Product $product) < $input = $request->all(); $validator = Validator::make($input, [ 'name' => 'required', 'detail' => 'required' ]); if($validator->fails())< return $this->sendError('Validation Error.', $validator->errors()); > $product->name = $input['name']; $product->detail = $input['detail']; $product->save(); return $this->sendResponse($product->toArray(), 'Product updated successfully.'); > /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy(Product $product) < $product->delete(); return $this->sendResponse($product->toArray(), 'Product deleted successfully.'); > >app/Http/Controllers/API/RegisterController.php
all(), [ 'name' => 'required', 'email' => 'required|email', 'password' => 'required', 'c_password' => 'required|same:password', ]); if($validator->fails())< return $this->sendError('Validation Error.', $validator->errors()); > $input = $request->all(); $input['password'] = bcrypt($input['password']); $user = User::create($input); $success['token'] = $user->createToken('MyApp')->accessToken; $success['name'] = $user->name; return $this->sendResponse($success, 'User register successfully.'); > >Теперь мы готовы к запуску RESTful API и Passport API. Давайте запустим наш пример — открывайте консоль и вводите команду:
php artisan serve
Убедитесь, что API использует следующие заголовки, как указано ниже:
'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$accessToken, ]
Список адресов с методами
- Login: метод:GET, URL:http://localhost:8000/oauth/token
- Register: метод:GET, URL:http://localhost:8000/api/register
- List: метод:GET, URL:http://localhost:8000/api/products
- Create: метод:POST, URL:http://localhost:8000/api/products
- Show: метод:GET, URL:http://localhost:8000/api/products/
- Update: метод:PUT, URL:http://localhost:8000/api/products/
- Delete: метод:DELETE, URL:http://localhost:8000/api/products/
Теперь вы можете запускать вышеприведенные адреса, как на скриншотах:

Вход API:

Регистрация API:

Список товаров API:

Создание товара API:

Показ товара API:

Обновление товара API:

Удаление товара API:
Наш Телеграм-канал — следите за новостями о Laravel.
Задать вопросы по урокам можно на нашем форуме.
- config/