Examples given is of In this guide we’ll look at a plugin named local_todo
(which is the plugin todo
in the local
directory) as an example.
Table of Contents | ||
---|---|---|
|
...
What is
...
GraphQL?
Concepts
For a detailed explanation of GraphQL concepts, please see our /wiki/spaces/~simonc/pages/119473875 documentation. However, if you just want to see the GraphQL API in action, please head straight to the quick-start guide further along in this page Create an internal query section.
Schema
...
types
In Totara, schemas are categorised based on their use cases. Each schema type - queries, mutations, types, etc. - follows specific rules about its availability and interaction interactions with other schema types. Totara defines three primary schema types: external, internal, and mobile.
External
...
schema
The external schema is used for defining APIs accessible to external systems. It serves as the “root” ‘root’ schema since it can be accessed by other schemas.
...
Code Block |
---|
server/local/todo/webapi/schema.graphqls |
Internal
...
schema
The internal schema, also referred to as ajax
in the codebase, is designed for internal client operations. It is isolated and not accessible to other schema types.
...
For more information, refer to Totara's Developer Documentationdeveloper documentation or check the quick-start guide below on creating an internal query within this document.
Mobile
...
schema
The mobile schema is tailored for APIs used by the Totara mobile Mobile app.
Mobile schemas are stored in the plugin's webapi/mobile/
directory. For example, in the local_todo
plugin, the mobile schema file would be located at:
Code Block |
---|
server/local/todo/webapi/mobile/schema.graphqls |
...
Create an
...
internal query
Create the schema
Create a
webapi
directory in your plugin directory. For example, for mylocal_todo
plugin, this would be in/server/local/todo/
.Under the
webapi
directory, create
...
an
ajax
directory.Create a
schema.graphqls
file under theajax
directory.In
schema.graphqls
, let’s define thetodo_item
type by adding the following:Code Block
...
language | graphql |
---|
type local_todo_item { id: core_id title: String completed_at: core_date }
This adds a new type withid
,title
andcompleted_at
, which we will have access to when using this type.
Create the query
We’ll start off our APIs with by creating a query to retrieve a list of the type todo_item
.
In
schema.graphqls
define the result we’ll get back from the query by defining the following type:Code Block Code Block language graphql type local_todo_items_result { items: [local_todo_item!]! }
Notice here we’ve used
!
in two places. This indicates the field is non-nullable. We’ve used this here to say that we always expect an array, by putting the exclamation mark on the outside of the array[...]!
. We also used to to say that the elements of the array cannot be null[my_type!]
.
Now we have the result defined, let’s define the query. We do this by extending the type
Query
and adding our query into it. Let’s do this:Code Block language graphql extend type Query { local_todo_items: local_todo_items_result! }
This defines that the query
local_todo_items
should return thelocal_todo_items_result
type we defined earlier
Creating the persisted query
The persisted query is a definition of the query for the frontend component to import. We name this file the query name, minus the component name of the plugin we’re working with.
...
Create the persisted query file in the
webapi/ajax/items.graphql
with the following:Code Block language graphql query local_todo_items { local_todo_items { items { id title completed_at } } }
Create the backend
Now we need to create the PHP backend to handle the query.
First we’ll create the directory for the query resolver by creating the following directory
/server/local/todo/classes/webapi/resolver/query
Now let’s create the query resolver class,
items.php
in the directory we just created.Code Block language php <?php namespace local_todo\webapi\resolver\query; use core\webapi\execution_context; use core\webapi\query_resolver; use local_todo\entity\item; class items extends query_resolver { /** * @inheritDoc * @throws \coding_exception */ public static function resolve(array $args, execution_context $ec) { global $USER; $items = item::repository() ->where('user_id', $USER->id) ->order_by('id') ->get(); return ['items' => $items]; } }
In this file we’ve defined the query resolve and we’re using the ORM of local_todo to return a list of items.
Now we create the type resolver directory
/server/local/todo/classes/webapi/resolver/type/
and the type resolver for itemitem.php
in the directory.Code Block language php <?php namespace local_todo\webapi\resolver\type; use core\webapi\execution_context; use core\webapi\type_resolver; class item extends type_resolver { /** * @param string $field - The field being requested * @param $source - In the case, source will be our `item` entity class as it's what's returned from the query resolver * @param array $args * @param execution_context $ec * @return mixed|void */ public static function resolve(string $field, $source, array $args, execution_context $ec) { return $source->$field; } }
Testing
...
queries and
...
mutations
To test your queries and mutations, please see our guide to using the developer GraphQL API: Making developer requests via a GraphQL client .