Часть 1. Сервер
Часть 2. Клиент
Часть 3. Мутации
Часть 4. Валидация. Выводы Порой при разработке API случается так, что необходимо не только лишь получать данные, но и вносить определенные изменения. Именно для этой цели существует то, что в GraphQL называется странным словом "мутация". Вдоволь наигравшись с клиентской частью, вернемся таки к нашему серверу и добавим несколько мутаций. Для мутаций нам необходимо иметь отдельную от query точку входа (MutationType), а сам функционал реализуется через параметры полей args и resolve. Вопрос: Могу ли я реализовать мутации через поля секции query? Хороший вопрос. Дело в том, что гипотетически это возможно, но архитектурно неправильно. А еще библиотека Apollo любит делать корневой запрос, т.е. имея всю структуру, запрашивает все, что возможно. Зачем она это делает, я не знаю, но предположительно, если засунуть в query методы вроде delete(), можете случайно лишиться ценного. /schema/mutations/UserMutationType.php: Совет. Старайтесь делать ваши функции resolve() как можно менее нагруженными. Как видите, GraphQL позволяет это сделать максимально. Переносите максимально всю логику в модели. Схема и API это лишь связующее звено между клиентом и сервером. Этот принцип касается не только GraphQL, а и любой серверной архитектуры. Аналогично /schema/mutations/AddressMutationType.php: Во время разработки своего сервера, внимательно следите за тем, чтоб не использовать мутацию для выборки, или query для изменения данных, потому что жесткой привязки, как таковой нет. Ну и корневой тип: /schema/MutationType.php: Если вы заметили, на прошлом шаге мы уже использовали кастомные типы из Types, хотя еще и не создали их. Этим собственно сейчас и займемся. Откроем же наш GraphiQL (а в соседней вкладке наш новосозданный клиент, чтобы убедиться, что данные таки меняются) и посмотрим на результат: Запрос:   Теперь попробуем изменить адрес и привязанного к нему юзера одним запросом: Запрос:  Чтобы увидеть изменения адреса, немного изменим наш шаблон:  Сразу попытаемся представить и сравнить с тем, как нужно изощриться, чтоб провернуть что-то подобное в RESTful архитектуре. А вообще, подобные вещи, насколько мне известно, перечат концепции REST-а, а в GraphQL это изначально заложено архитектурно. Пока мы не перешли к клиенту разберемся что такое variables в GraphQL. С практическим их применением вы познакомитесь при использовании в мутациях в клиенте, а пока не заморачивайтесь над этим, т.к. изначально их польза не так заметна. Изменим немного нашу мутацию с использованием переменных: Запрос: Переменные: Примечание. Технически, переменные приходят отдельным POST-параметром variables. Окно GraphiQL (поле для ввода переменных нужно просто вытянуть снизу, да, оно у вас тоже есть):   Может показаться, что переменные удобны, когда в нескольких местах используется одно и то же значение, но на самом деле, на практике это редкая ситуация, и нет, это не основное их предназначение. Более полезным является возможность сразу же произвести валидацию поля. Если попытаться в переменную передать неверный тип и/или если вовсе не передать, в случае когда поле обязательное, запрос на сервер не уйдет. Но основное удобство (я бы даже сказал необходимость) использования вы ощутите в клиенте. Как вы помните, все наши GraphQL-запросы мы договорились хранить в models (не почти все, а все-все), посему добавим нашу новую мутацию. models/user.js: Чтобы было интереснее, создадим новый компонент, заодно посмотрим как работаем механизм событий для общения между компонентами (никакого отношения к GraphQL, поэтому без энтузиазма). Создаем директорию /src/update-user-address и ложим туда традиционно 2 файла: update-user-address.html и update-user-address.js. Примечание. Если хотите назвать свой компонент как-нибудь по-другому, имейте ввиду, что существует неочевидное требование к именованию. Дело в том, что кастомный компонент в имени должен обязательно содержать "-". Вот так. /src/update-user-address/update-user-address.js: /src/update-user-address/update-user-address.html: Чтобы мы могли тут же обновить данные в соседнем компоненте для их вывода после изменения, добавим в него event listener и метод для обновления GraphQL-запроса. src/graphql-client-demo-app/graphql-client-demo-app.js: index.html: entry.js: Ну и для начала соберем webpack (если вы все еще не избавились от него): Открываем браузер и получаем что-то подобное:  Конечно же картинка не позволяет доказать, что данные в верхней части меняются сразу же после нажатия на кнопку Send, но вам ничего не стоит попробовать это самому. К слову, все изменения предусмотрительно залиты на github: клиент и сервер. Говоря откровенно, данная архитектура совсем не оптимальна, т.к. необходимо доработать ее таким образом, чтобы выполнялся один запрос и данные подтягивались во все места интерфейса. Но это уже проблема не GraphQL. В следующей (заключительной) части статьи мы рассмотрим, как реализовать валидацию в мутациях, и наконец сделаем выводы по преимуществам и недостатками перехода на GraphQL на основе полученного опыта.