Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JSON API на Битриксе с использованием \Techdir\...

JSON API на Битриксе с использованием \Techdir\PhpInterface

Евгений Неверов, 23 июля 2018 года

Avatar for Evgeny E. Neverov

Evgeny E. Neverov

July 23, 2018
Tweet

More Decks by Evgeny E. Neverov

Other Decks in Programming

Transcript

  1. Где держать AJAX- обработчики? Где обычно: • Папка шаблона сайта

    • Папка шаблона компонента • Папка /ajax или подобная в корне
  2. /api/index.php <?php if ($_SERVER['REQUEST_METHOD'] @@=== 'GET') { define('BX_SECURITY_SESSION_READONLY', true); }

    require $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/ main/include/prolog_before.php"; $APPLICATION@->IncludeComponent('techdir:api', '', array( 'API_NAMESPACE' @=> '@\\Techdir@\\PhpInterface@\\Api', ), false); require $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/ main/include/epilog_after.php";
  3. /api/index.php <?php if ($_SERVER['REQUEST_METHOD'] @@=== 'GET') { define('BX_SECURITY_SESSION_READONLY', true); }

    Общее правило: GET-запросы для выборки данных, POST — для изменения данных За счёт этого в GET-запросах можно включить readonly-режим сессий и не страдать от блокировки сессий.
  4. /api/index.php $APPLICATION@->IncludeComponent('techdir:api', '', array( 'API_NAMESPACE' @=> '@\\Techdir@\\PhpInterface@\\Api', ), false); API_NAMESPACE

    — это базовый Namespace внутри которого будет производиться поиск класса для вызова. Если не указать, будет ошибка.
  5. Поиск класса 1. Берём путь REQUEST_URI: /api/path/to/method/ 2. Удаляем из

    пути реальный путь до папки со скриптом компонента: /api/index.php 3. Оставшаяся часть — неймспейс + имя класса, к которому слева прикрепляется базовый неймспейс: \Techdir\PhpInterface\Api\path\to\method Класс наследуется от базового класса
  6. Обработка запроса 1. Компонент вызывает: Api\Path\To\Method@::_run($_GET, $_POST); 2. _run проверяет:

    — CORS-запрос, — Необходимость авторизации, — Требуемые параметры. 3. _run запускает метод run() и возвращает результат в компонент. 4. Компонент оборачивает результат в JSON и возвращает клиенту.
  7. Но есть и плюсы • Чистота и простота кода •

    Быстрая локализация проблем • Ну@@... и всё. Плюсы кончились.
  8. Пример /techdir/lib/api/user/info.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class Info extends

    Base { protected static function run() { global $USER; if (!$USER@->IsAuthorized()) { return false; } return \CUser@::GetByID($USER@->GetID())@->Fetch(); } }
  9. Требуем авторизацию /techdir/lib/api/user/secureinfo.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class SecureInfo

    extends Base { protected static $needAuth = true; protected static function run() { return \CUser@::GetByID( $GLOBALS['USER']@->GetID() )@->Fetch(); } }
  10. Требуем параметры /techdir/lib/api/user/get.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class Get

    extends Base { protected static $needAuth = true; protected static $needParams = ['id']; protected static function run() { return \CUser@::GetByID(static@::$_get['id']) @->Fetch(); } }
  11. Требуем параметры Формат $needParams: [ 'key1' @=> [ 'required' @=>

    true, @// true / false, 'filter' @=> FILTER_VALIDATE_INT, @// filter_var() 'from' @=> 'any' @// 'get', 'post' ], @@... ]; Или просто названия переменных (тогда required @=> true, filter @=> any, from @=> any) Фильтры: http:@//php.net/manual/ru/filter.filters.validate.php
  12. Собственная проверка параметров /techdir/lib/api/user/getbyemail.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class

    GetByEmail extends Base{ protected static $needAuth = true; protected static function checkParams() { return check_email(static@::$_get['email']); } protected static function run() { } }
  13. Возвращаем ошибки /techdir/lib/api/user/search.php class Search extends Base { protected static

    $needAuth = true; protected static $needParams = ['login' @=> ['filter' @=> FILTER_VALIDATE_EMAIL]]; protected static function run() { $arUser = \CUser@::GetByLogin(static@::$_get['login']) @->Fetch(); if (!isset($arUser['ID'])) { static@::setResponseStatus(404); return ['error' @=> true, 'error_code' @=> 'E_USER_NOT_FOUND']; } return $arUser; } }
  14. Межклассовая коммуникация /techdir/lib/api/user/info.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class Info

    extends Base { protected static function run() { global $USER; if (!$USER@->IsAuthorized()) { return false; } return \CUser@::GetByID($USER@->GetID())@->Fetch(); } }
  15. Межклассовая коммуникация /techdir/lib/api/user/info2.php <?php namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class Info2

    extends Base { protected static function run() { $userId = $GLOBALS['USER']@->GetID(); return Get@::_run(['id' @=> $userId], []); } } DRY – Don't Repeat Yourself!
  16. Межклассовая коммуникация На самом деле, можно даже вот так:
 <?php

    namespace Techdir\PhpInterface\API\User; use Techdir\PhpInterface\API\Base; class SomeClass extends Base { protected static function run() { return SomeOtherClass@::run($a, $b, $c); } }