API
PHP
Yii
Комментарии 28
0
Оффтоп
«Мутации в GraphQL заменяете на экшны для RESTa» — опять путают REST и RPC. В REST строго ограниченное количество «экшнов», они не пользовательские, это — глаголы HTTP. Прямых аналогов мутаций GraphQL или экшнов RPC в REST нет, выходящие за рамки CRUD операции прикладной области должны быть выражены отдельными ресурсами-существительными (например, «квитанциями об операции» или «приказами»). Именно ограниченность количества экшнов над ресурсами и фиксированность их семантики и помогает держать архитектуру приложения в чистоте и не стрелять себе творчески в ногу.
0
Опять путают REST-архитектуру и HTTP в качестве протокола прикладного уровня. Система может использовать HTTP полностью забивая на его семантику, но пои этом не переставпть быть REST
0
И зачем же вы путаете REST и HTTP? Чтобы оставаться в рамках архитектурных ограничений REST, но забивать на HTTP, придётся переизобрести собственный ограниченный набор CRUD-методов над ресурсами. Суть претензии от этого не меняется, «пользовательских» мутаций и экшнов в REST нет, есть только ограниченный набор операций над любыми ресурсами. Претензия вашим замечанием не устраняется: мутации GraphQL — это аналог экшнов со свободной семантикой из подхода RPC, но совсем не аналог строго ограниченных операций над ресурсами из REST.
0

Нет фундаментальных ограничений на количество оепраций в REST. Более того, сервер сам (может/должен?) сообщать о доступных операциях касающихся конкретного ресурса, отдавая клиенту его представление вместе с метаданными соотвествующими (единого стандрта описания нет) операции, например url и метод, которыми нужно вызвать сервер, чтобы изменить ресурс. Есть общепринятые и частично специфицированные принципы построения CRUD операций по HTTP, но REST не накладывает ограничений на общее количество или строгое соблюдение семантики HTTP. Более того REST не требует HTTP в принципе. Просто самый распространенный протокол для создания REST-подобных серверных API. "Подобных" потому что не встречал в реальной жизни полноценных реализаций REST через HTTP — те или иные компромиссы между практичностью и пуризм всегда есть.

0
Вы явно не в курсе, о чём REST, зачем в нём ограничения (и весь тот ворох RFC об ошибках и правилах обработки операций над ресурсами). Попробуйте начать с раскрытия аббревиатуры, уже в ней что-то должно вас натолкнуть на мысль об ограниченности глаголов для работы с ресурсами. Клиент с сервером обменивается только изменениями репрезентаций ресурсов по унифицированному протоколу, независимому от семантики ресурсов в прикладной задаче.
0

Какие ещё RFC по REST? Вы не путаете с RFC по HTTP? А сам REST не путаете с типичными (стандарта нет) HTTP RESTful API? Какие принципы REST запрещают мне создать свой унифицированный прикладной протокол для своего API, используя HTTP лишь как транспортный, с минимальной оглядкой на его семантику?

0
Вы просто несёте бред, перестаньте. Изучите, что такое REST и зачем он, тогда поймёте, насколько глупо звучит ваше «без оглядки на его семантику». Вы дистанцировали REST от его реализации в виде HTTP, избавили от его семантики, что же вы вообще под ним подразумеваете? (Это риторический вопрос.)
0

Я свою точку зрения аргументирую, а вы?


REST — это архитектурные принципы (одни из) построения распределенных систем, HTTP — протокол прикладного уровня, поддерживающий эти принципы. Но никто не запрещает нам использовать его лишь в качестве траспортного, игнорируя его прикладную семантику, и реализовать архитектуру распределенной системы по REST, наполняя части HTTP-сообщений своей прикладной семантикой, например, передавая идентификатор ресурса в теле запроса, а действие над ресурсов в URI и создавая тот набор операций над ресурсом, который нам нужен, а не ограничиваться данными в HTTP.


Кто желает использовать семантику HTTP в API — тот использует и называет свои HTTP API "RESTful" (хотя на практике полностью семантику HTTP и принципы REST до конца не использует никто и потому эти API скорее RESTish чем RESTful), а кто не хочет — не использует, не называя свои API "RESTful", но реализуя принципы REST, с точки зрения HTTP представляя, например, всю систему в виде одного ресурса или представляя операции в виде ресурсов, а идентификатор передавая в теле запроса.


REST говорит нам, что должны быть клиент и сервер, что должны быть однозначно идентифицируемые ресурсы, их представления и унифицированный набор операций над ними и. т. д… Он ничего нам не говорит о том, как реализовывать всё это и, в частности, какой набор унифицировааных операций должен быть и в каком масштабе это унификация должна проходить.

-1
Я вам ничего не запрещаю, делайте, что хотите. У вас, похоже, своя война в голове, в которую меня втягивать не нужно.
0

В общем ляпнули что-то умное, оскорбили походя, но никаких аргументов?

0
Как видим, сработало первое правило, которое говорит о том, что поле — обязательное.

А можно как-то в GraphiQL подсказать что поле не может быть пустым?
0

Конечно. Для этого нужно в схеме в аргументе прописать обертку:


...
'args' => [
    ...
    'email' => Type::nonNull(Type::string()),
],
...

Так сработает валидация уже на уровне схемы, т.е. не доходя до модели, и сам GraphiQL это уже будет знать, и подчеркивать красным.

0
Ну, не совсем, надо указать что строка не может быть пустой а не null. Другой пример для чисел, указать что цена например должна быть больше нуля?
0
Type::nonNull() указывает на то, что этот параметр обязательно должен быть передан. Честно говоря с настолько кастомной валидацией, о которой вы говорите, средствами самого GraphQL не сталкивался.

Насколько мне известно, валидация на уровне GraphQL ограничивается корректностью самого запроса (правильные названия полей и структура); обазательное/необязательное поле; и правильный ли тип (Int, String, ...). Такие валидации GraphiQL покажет. Более серьезные валидации с проверкой, например, уникальности поля в БД, и т.п. не касаются самой схемы, потому никак не могут быть реализованы на ее уровне, потому GraphiQL о них ничего не узнает.
0

Ну как вариант, да. Но это не валидация, а лишь нотификация.


Для этого нужно использовать InputTypes. Я, честно говоря, с ними еще не работал, но пора начинать. Они впринципе как улучшают архитектуру так и расширяют возможности.

0
Так же хочу немного поправить, то о чем я написал. Обязательность аргумента и обязательность поля на уровне ActiveRecord будет работать по разному, т.к. если поле не передано, но оно и так уже не пустое в редактируемой модели, все пройдет ОК. А при обязательности в схеме наше поле будет запрашиваться в любом случае.
0
Хорошая серия статей. Хочу ещё) Было бы здорово, если были раскрыты темы аутентификации, пагинации и безопасности
0

Спасибо! Значит есть над чем работать. Задача пагинации уже стоит на будущее, с авторизацией на самом деле все просто, там для статьи мало информации, хотя я находил статьи по авторизации в GraphQL, нужно почитать, о чем именно там пишут. Насчет безопасности, не знаю что может быть специфичного именно касательно GraphQL.

0

Ну да, аутентифицироваться можно через токен. Но вот разграничение прав на доступ к запросам и мутациям. Особенно интересует, как решается такая проблема:


У разработчика Х есть возможность посмотреть основные данные профиля пользователя. У пользователя есть список авто, который доступен через поле "auto". И у разработчика Х нет никаких прав на просмотр автомобилей. Как это решается? Хорошо, тут мы можем просто выдать пустой массив с авто. Но что делать, если у Х нет прав на просмотр некоторых полей профиля? Например email, который доступен только избранным? Оставлять поле пустым при запросе (как это фильтровать)? Как тогда защитить поля от мутаций? Писать отдельные мутации для каждого поля отдельно (updateUserEmail, updateUserPhone)?


В GraphQL легко решается вопрос характера: могу ли я делать что-то или не могу ничего сделать, но сделать что-то сложнее этого будет не просто. Возможно, я просто ничего не понимаю. Если не прав, объясните, пожалуйста.


В плане безопасности: глубокие, рекурсивные запросы, которые могут сильно нагрузить сервер (user->friends->friends->friends->friends)


В плане производительности: проблемы характера N+1


Ну и конечно же пагинация и сортировка: если у меня в ВК 500 друзей, но мне нужны только 6 случайных для отображения в левом столбике с друзьями, а не все (как пример)


И еще: есть ли в GraphQL какой-нибудь простой метод создания CRUD структуры, которая бы легко меняла REST схему. Пока что я не вижу простого метода, кроме как создания трех мутаций для каждого отдельного случая (create, update, delete).


Возможно ли как-то объединить схему GraphQL и класс Yii2, чтобы схема содержалась внутри модели AR или даже вытягивалась из нее?

0

Касательно вопроса с доступом, это классическая система ролей. Фреймворк всегда знает, аутентифицированного юзера, и всю информацию можно вытащить в любом месте. Как вариант, мы можем в зависимости от роли (или по другому условию) генерировать разную схему.


В GraphQL легко решается вопрос характера: могу ли я делать что-то или не могу ничего сделать, но сделать что-то сложнее этого будет не просто. Возможно, я просто ничего не понимаю. Если не прав, объясните, пожалуйста.

Не очень понял о чем вы. Все, чего не может GraphQL, может фреймворк, а то, что может фреймоворк, можно завернуть в средства GraphQL. Именно это я показал на примере того, как реализовал валидацию.


Ну и конечно же пагинация и сортировка: если у меня в ВК 500 друзей, но мне нужны только 6 случайных для отображения в левом столбике с друзьями, а не все (как пример)

Первое, что приходит в голову, это банально добавить параметры page — номер страницы, offset смещение (или cpp — count per page) — классические параметры для паджинации, которые мы потом используем в выборке из БД. Возможно есть и другие способы.


И еще: есть ли в GraphQL какой-нибудь простой метод создания CRUD структуры, которая бы легко меняла REST схему. Пока что я не вижу простого метода, кроме как создания трех мутаций для каждого отдельного случая (create, update, delete).

Я пока тоже ничего проще не вижу, но это как раз решается тем, о чем вы написали:


Возможно ли как-то объединить схему GraphQL и класс Yii2, чтобы схема содержалась внутри модели AR или даже вытягивалась из нее?

Существуют расширения под Yii, но как я и писал, мой выбор пал все-же на базовое. Возможно если ковырнуть, оно и упростит работу по банальному CRUD, т.к. автоматическое генерирование схемы из активрекорда действительно лежит на поверхности.

0
Но что делать, если у Х нет прав на просмотр некоторых полей профиля? Например email, который доступен только избранным? Оставлять поле пустым при запросе (как это фильтровать)? Как тогда защитить поля от мутаций? Писать отдельные мутации для каждого поля отдельно (updateUserEmail, updateUserPhone)?

Отдавать "403" при попытке получить недоступные поля-записи, или давать специальные значения (пустые или что-то вроде "доступ запрещен"). Отдавать 403 при попытках мутировать недоступные поля или игнорировать.

0
Насчет безопасности, не знаю что может быть специфичного именно касательно GraphQL.

Загрузить сервер большой вложенностью запроса.

0
Как в GraphQL различаются типы ошибок? Если при обновлении записи ошибка возникла не в валидации, а в правах доступа?

На клиенте при ошибке валидации мне нужно подсветить поля формы, а при нехватке прав доступа показать сообщение (toast).
0

Можете сделать аналогичный тип валидации PermissionErrorType, тогда ваша мутация будет выглядеть примерно таким образом:


...
update(...) {
  ...on PermissionError {
    errorText
  }
  ...on ValidationErrorsList {
    ...
  }
  ...on User {
    firstname
  }
}

ну а в resolve() вы должны на нехватку пермишнов выплюнуть соостветственный формат. Другой вариант это вернуть просто 401, который для этого и предназначен.

Только полноправные пользователи могут оставлять комментарии. , пожалуйста.