За последние 24 часа нас посетили 22512 программистов и 1008 роботов. Сейчас ищут 724 программиста ...

JSON API для тех, кто в танке [РУКОВОДСТВО]

Тема в разделе "PHP для новичков", создана пользователем Roman __construct, 19 дек 2019.

Метки:
  1. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Это ответ на вопрос из соседнего топика, но, уверен, что пригодится и другим новичкам. Просто базовые принципы JSON API, ничего лишнего.

    1. Интернет можно упрощенно представить себе как совокупность компьютеров, которые общаются между собой по протоколу HTTP

    2. Протокол HTTP подразумевает формат "Запрос - Ответ". То есть, клиент (например, ваш браузер) отправляет к удаленному серверу (где находится нужный вам сайт) запрос, и получает на него какой-то ответ. Две части цикла: 1) Запрос к серверу, 2) Ответ от сервера. Всё, больше в интернете никакой магии нет :D

    3. Когда вы делаете "обычный PHP-сайт" вы ни о чем подобном, как правило, не задумываетесь, ну, разве что если у вас начинаются ошибки вроде "Заголовки уже посланы..." - и вы тогда начинаете недоумевать - "Какие еще заголовки? Я никуда ничего не посылал же..." - но когда вы, следуя современному тренду, решаете разделить сайт на фронт и бэк, то эта тема неизбежно всплывает, потому что вам требуется наладить обмен данными между фронтом и бэком.

    4. Чисто технически, фронт и бэк проще всего представить, как два независимых приложения. Одно из которых написано (чаще всего) на JavaScript, и выполняется в браузере пользователя вашего сайта - это фронт, а другое написано на PHP, и выполняется на вашем сервере - это бэк.

    5. Таким образом, ваша задача, как программиста, сводится к тому, чтобы наладить обмен данными между этими двумя приложениями (фронтом и бэком).

    6. Описание способов, которыми фронт и бэк общаются между собой, называется - API.

    7. И в таком API может использоваться формат JSON.

    Перейдем к конкретике, пока ваши мозги не поплыли от обилия пустых значений :)

    1. Пользователь вбивает в адресную строку браузера http://myjsonapi.ru и жмет "Ввод"

    2. Браузер обращается к серверу на котором находится ваш сайт http://myjsonapi.ru, скачивает с него приложение-фронт (которое вы написали на JavaScript), и начинает его исполнять

    3. Допустим, вы прописали на фронте, что при запуске в браузере, оно будет сообщать бэку об этом. И теперь происходит вот что:

    3.1 Ваше приложение-фронт формирует строку в формате JSON, например:

    Код (Javascript):
    1. ["frontstatus":"ok"]
    3.2 Посылает запрос, вашему приложению-бэк, которое вертится, например, на том же сервере, и доступно по адресу http://myjsonapi.ru:3000 (то есть, адрес тот же, просто порт 3000-й)

    3.3 И в теле запроса как раз и помещает это JSON-строку

    Код (Javascript):
    1. ["frontstatus":"ok"]
    3.4 Запрос может быть и GET, и POST, и придумайте-что-то-еще - без разницы.

    3.5 Допустим это будет GET-запрос

    HTML:
    1. http://myjsonapi.ru:3000?req=["frontstatus":"ok"]
    4. Ваше приложение-бэк на PHP получает этот запрос, и теперь JSON-строка содержится в переменной

    PHP:
    1. $_GET['req']
    и вы можете преобразовать ее в PHP-формат так:

    PHP:
    1. $json = Json_decode($_GET['req']);
    вуаля :) теперь в переменной $json содержится ассоциативный массив, с одной парой ключ-значение

    PHP:
    1. ['frontstatus' => 'ok']
    Данные с фронта на бэк - переданы!

    5. Теперь передадим данные с бэка на фронт:

    PHP:
    1. $jsonToFront = Json_encode(['backstatus' => 'ok']);
    теперь у нас в $jsonToFront находится строка

    Код (Javascript):
    1. ["backstatus":"ok"]
    и отправим ее на фронт, например так:

    PHP:
    1. $response = file_get_contents('http://myjsonapi.ru?res='.$jsonToFront);
    6. Соответственно, на фронте теперь извлекаете как-то там (JS я здесь не буду рассматривать) значение параметра res - этим значением и будет JSON-строка

    Код (Javascript):
    1. ["backstatus":"ok"]
    7. Круг замкнулся :) Мы передали данные с фронта на бэк, и с бэка на фронт в формате JSON.

    Это и есть JSON API :)

    Все вопросы, уточнения, исправления ошибок )) просьба писать в комментариях.
     
  2. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
  3. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    да я вот тоже написал это и понял, что наверное такие туторы лучше просто кодом писать и всё ))

    ну, можно и с картинками комбинировать, да
     
  4. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    dsdsd.jpg
    Код (Javascript):
    1. var test = JSON.stringify({test: 1233});
    2. getAjax( 'index.php?&test='+test, function(data){
    3.         var json = JSON.parse(data);
    4.         console.log( json);
    5.         console.log( typeof json);
    6. });
     
    Roman __construct нравится это.
  5. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Респект, бро!
     
  6. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    А теперь тоже самое для Laravel / Passport / Axios )
     
  7. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    дадада, мне тоже пожалуйста)))))))))))

    если без шуток - то можно было бы написать кучу чудесных туторов, но я совершенно не понимаю, как из этого сделать хоть какие-то внятные деньги

    единственный вариант - это на английском делать

    но для меня это боль)))
    --- Добавлено ---
    ...вообще, тут если по хорошему, не столько именно по "Laravel / Passport / Axios" надо писать, сколько по OAuth2 блок-схемы рисовать :)

    И если совсем честно - меня уже пару месяцев как подмывает изобрести какой-то велосипед вместо OAuth / JWT - слишком уж они муторные какие-то

    Это должно быть радикально проще
     
  8. JastaFly

    JastaFly Активный пользователь

    С нами с:
    4 ноя 2019
    Сообщения:
    46
    Симпатии:
    3
    Спасибо) теперь стало немного яснее. Сейчас я хочу сделать как-то так:
    1. Фронт будет передавать беку команды. Например, страница загружается, запускается функция которая отправляет на бек следующую команду:
    ["load":"10"]
    Что значит получить 10 записей из соответствующий таблицы в БД. Бек ломится в базу, получает от туда данные и возвращает их на фонт, а фонт уже распределяет их по интерфейсу.
    2. Юзер скролит вниз, снова вызываем туже функцию, получаем ещё 10 записей.
    3. Нужно отсортировать по дате, отправляем другую команду ["sort-date":"false"], где фолс это текущее состояние сортировки (убывание/возрастание).
    Ну и так далее. Я всё верно понял???
     
  9. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    Найдите любой более менее серьезный сервис у которого есть АПИ и посмотрите как там это работает..

    Если Вы что то хотите получить от сервера - должно идти через GET запросы.. и ИМХО json строка в GET запросе не очень удачная мысль..

    Если Вы хотите что то отредактировать/удалить - это должно идти через POST запросы... или же если хочется быть кошерным то тогда используйте PUT PATCH DELETE https://www.restapitutorial.com/lessons/httpmethods.html

    То что возвращает сервер должно возвращаться с кодом состояния.. по ссылке выше есть коды ошибок которые должна АПИшка возвращать..

    Ссылки для АПИшки стройте таким образом что бы было понятно что вы делаете....

    например у вас страница с постами блога

    GET запрос к /posts - должна показывать все ваши посты
    POST запрос к /posts - должен создавать новый пост..

    GET к /posts/create - это страница с формой создания нового поста
    GET к /posts/1/edit - это страница редактирования существующего поста
    а POST к /posts/1 это сохранение того что вы отредактировали..

    на странице с постами у вас всегда будут дополнительные параметры.. их можно не парится прописывать в ЧПУ.. просто передавайте гет параметрами в строке
    /posts?skip=25&order=name&by=desc

    имена гет параметров старайтесь давать такие как у вас названия столбцов в табличке.. это избавит от проблем адаптации при запросах к базе данных))
     
  10. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    А куда проще JWT в чистом виде? Отдал токен пользователю и пусть ходит с ним сколько захочет.
     
  11. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    если нужно получить еще 10 записей то делаете вот так вот

    /posts?skip=10&order=name&by=desc

    10 это сколько пропустить записей с начала.. при следующем запросе надо будет сделать /posts?skip=20&order=name&by=desc и т.д.
     
  12. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    ну, не совсем так)) там ведь есть и срок годности и обновление токена.

    в общем, это конечно кому как, но мне в целом авторизация в Laravel кажется избыточно навороченной

    постоянно хочется банально свою миддлварь прописать и не париться уже

    такие желания ведь не на пустом месте возникают, согласись же :)
    --- Добавлено ---
    Могу дать хороший совет:

    - Не бегите впереди паровоза :)

    То есть, сначала просто реализуйте вот это:

    то есть сделайте это в реальности, чтобы оно работало на 100%

    а уже потом начните постепенно усложнять

    добавлять функционал по одному

    сначала автозагрузку при скроллинге, потом запросы с сортировкой по дате, и т.д.

    это общий принцип, следуя которому вы всегда будете побеждать :)
     
  13. JastaFly

    JastaFly Активный пользователь

    С нами с:
    4 ноя 2019
    Сообщения:
    46
    Симпатии:
    3
    Это понятно. Просто хочу убедиться что я хотя-бы мыслю в правильную сторону
     
  14. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Это ты про Passport? Есть же альтернатива https://laravel.com/docs/5.8/api-authentication прям вот проще некуда - это даже не jwt.
     
  15. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    это который "просто токен"?))

    ну эт да, это норм))

    но они там везде настоятельнорекомендуют использовать паспорт ))
     
  16. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Ну, потому что он покрывает процентов 90 задач и при этом делает всё более-менее безопасно, в отличии от того, что по ссылке выше. А вот чистого JWT, кстати, из коробки нет вообще.
     
    Roman __construct нравится это.
  17. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Добавлю немного по теме нашего разговора:

    1. API Token - когда тебе нужно сделать доступ к данным, причем твоя аудитория, хм... не сильно в теме. К примеру что-то, что будет выгружаться в 1Cку (да простят меня нормальные 1сники). Генерируешь строку, где-нибудь в кабинете её выводишь, чувак с ним стучится (можно ведь даже не в заголовке, а параметром к ссылке) и данные - его. Плюсов два: во-первых это легко, во-вторых, ключ всегда можно отозвать и заменить новым. Минусы: доступ открыт всем у кого есть ключ и он скорее всего вечный, (из контекста) ключ обязательно засветится где-нибудь в логах, а то и в истории браузера. Короче, подходит исключительно для данных, утечка которых не критична для обеих сторон.

    2. Passport + Socialite. Обычно используется в связке. Позволяет реализовать единую точку входа (ну типа как Паспорт в Яндексе или Аккаунт в Гугле) - в комплекте идут вход по паролю, через другие OAuth-сервисы (гугл, фб и т.п.), в т.ч. и ваш (т.е. можно сделать свою кнопку "войти через нашу точку входа") и полностью отделить бэк от фронта (т.е. сам сайт делается отдельно, всё общение с бэком через API ну и передача токенов серией редиректов). Кроме всего этого, позволяет реализовать отдельный слой доступа через "клиентов", как ваших, так и созданных пользователями, которые могут получить доступ к данным минуя весь этот обмен токенами.

    3. JWT - в Laravel не реализован, т.к. действительно, в большинстве случаев лучше использовать Passport. Собственно, у JWT как механизма верификации пользователя и его прав есть только одно несомненное преимущество - stateless, т.е. вам не нужно хранить где-то выданный токен, а значит и проверять его вы можете не только там где он был выдан, а вообще везде где можно получить доступ к secret. Это имеет как свои плюсы: токен самодостаточен и вам не нужно куда-то стучаться для его проверки, так и минусы: если у токена нет времени жизни, то он станет вечным, ведь способа отозвать его у вас нет. Ну и, пожалуй, главное - не смотря на то, что выглядит токен внушительно, в большинстве случаев механизм не предполагает шифрование передаваемых внутри него данных, потому ничего критичного внутри самого токена передавать не нужно.
     
    Roman __construct нравится это.
  18. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    А зачем file_get_contents?
     
  19. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    всмысле?

    а как бы ты запрос к фронту сделал?
     
  20. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    А зачем мне вообще это делать? Фронт мне по такому запросу вернёт какой-нибудь бред типа
    HTML:
    1.  
    2.  
    3. <!doctype html>
    4. <html lang="en">
    5. <meta charset="utf-8">
    6. <title>AuditBase</title>
    7. <base href="/">
    8. <link href="https://fonts.googleapis.com/css?family=Roboto+Slab:300,400&amp;subset=cyrillic,cyrillic-ext" rel="stylesheet">
    9. <meta name="viewport" content="width=1280, initial-scale=1">
    10. <link rel="icon" type="image/x-icon" href="favicon.ico">
    11. </head>
    12. <app-root></app-root>
    13. <script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="styles.js" type="module"></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script></body>
    14. </html>
    15.  
    --- Добавлено ---
    Это, если что, с реального текущего проекта
     
  21. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Аааа... вот ты о чем...))

    2All: братюни)) вернуть ответ ответ с бэка на фронт можно и просто через echo например:

    PHP:
    1. echo '["backstatus":"ok"]';
    или если это, скажем, Laravel, то через response()

    в общем, тут возможны варианты, и много :)
     
  22. Vladchucha

    Vladchucha Активный пользователь

    С нами с:
    12 ноя 2018
    Сообщения:
    167
    Симпатии:
    7
    Адрес:
    Nürnberg
    Тема называется - Для тех кто в танке, т.е. для меня.
    Так вот, господа учителя, для начала мне непонятно,
    на кой лысый черт это все надо. ?
    То есть если хочу передать в PHP что-то, то есть просто $_GET,$_POST.....
    Если мне приспичило из РНР (бэк теперь ?) передать в JS,
    то передаю скажем так
    HTML:
    1. <script language="JavaScript">
    2.     function Box(text)
    3.     {
    4.         alert(text);
    5.         document.logon.submit();
    6.     }    
    7.    </script>
    8. </head>
    9. <?php
    10. $action = $_SERVER['PHP_SELF'];
    11. $jsText = $_SERVER['REQUEST_METHOD'] == 'POST' ? 'ВВВВВВВВ' : 'ААААААААf';
    12. ?>
    13. <form action="<?=$action?>" method="post" name="logon">
    14.   <br/>
    15.   <input type="button" value="Klick mich!" onClick="Box('<?=$jsText?>');"/>
    16. </form>
    В общем с самого начала не понимай моя танка.
     
  23. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Смысл в том что серверная часть полностью отделена от клиентской и общается с ней посредством API.

    Иными словами, нам теперь неважно на чем именно написан клиент и на какой платформе исполняется. Это и браузер в Windows может быть, и приложение в айфоне, всё что угодно, наш сервер будет работать с любым клиентом.