Getting started
- Server Requirements
- What you will need to run GraphQL on a web server
- Activating the default server
- Open up the default server that comes pre-configured with the module
- Configuring your schema
- Add a basic type to the schema configuration
- Building the schema
- Turn your schema configuration into executable code
- Building a schema with procedural code
- Use PHP code to build your schema
- Deploying the schema
- Deploy your GraphQL schema to a test or production environment
Building a schema with procedural code
Sometimes you need access to dynamic information to populate your schema. For instance, you may have an enum containing a list of all the languages that are configured for the website. It wouldn't make sense to build this statically. It makes more sense to have a single source of truth.
Internally, model-driven types that conform to the shapes of their models must use procedural code to add fields, create operations, and more, because the entire premise of model-driven types is that they're dynamic. So the procedural API for schemas has to be pretty robust.
Lastly, if you just prefer writing PHP to writing YAML, this is a good option, too.
One thing you cannot do with the procedural API, though it may be tempting, is define resolvers on the fly as closures. Resolvers must be static methods on a class, and are evaluated during the schema build.
Adding executable code
We can use the execute
section of the config to add an implementation of SchemaUpdater
.
SilverStripe\GraphQL\Schema\Schema:
schemas:
default:
config:
execute:
- 'App\GraphQL\MySchema'
Now just implement the SchemaUpdater
interface.
// app/src/GraphQL/MySchema.php
namespace App\GraphQL;
use SilverStripe\GraphQL\Schema\Interfaces\SchemaUpdater;
use SilverStripe\GraphQL\Schema\Schema;
class MySchema implements SchemaUpdater
{
public static function updateSchema(Schema $schema): void
{
// update here
}
}
Example code
Most of the API should be self-documenting, and a good IDE should autocomplete everything you need, but the key methods map directly to their configuration counterparts:
- types (
$schema->addType(Type $type)
) - models (
$schema->addModel(ModelType $type)
) - queries (
$schema->addQuery(Query $query)
) - mutations (
$schema->addMutation(Mutation $mutation)
) - enums (
$schema->addEnum(Enum $type)
) - interfaces (
$schema->addInterface(InterfaceType $type)
) - unions (
$schema->addUnion(UnionType $type)
)
namespace App\GraphQL;
use App\Model\MyDataObject;
use SilverStripe\GraphQL\Schema\Field\Query;
use SilverStripe\GraphQL\Schema\Interfaces\SchemaUpdater;
use SilverStripe\GraphQL\Schema\Schema;
use SilverStripe\GraphQL\Schema\Type\Type;
class MySchema implements SchemaUpdater
{
public static function updateSchema(Schema $schema): void
{
$countryType = Type::create('Country')
->addField('name', 'String')
->addField('code', 'String');
$schema->addType($countryType);
$countriesQuery = Query::create('readCountries', '[Country]!')
->addArg('limit', 'Int');
$schema->addQuery($countriesQuery);
$myModel = $schema->createModel(MyDataObject::class)
->addAllFields()
->addAllOperations();
$schema->addModel($myModel);
}
}
Chainable setters
To make your code chainable, when adding fields and arguments, you can invoke a callback to update it on the fly.
$countryType = Type::create('Country')
->addField('name', 'String', function (Field $field) {
// Must be a callable. No inline closures allowed!
$field->setResolver([MyResolverClass::class, 'countryResolver'])
->addArg('myArg', 'String!');
})
->addField('code', 'String');
$schema->addType($countryType);
$countriesQuery = Query::create('readCountries', '[Country]!')
->addArg('limit', 'Int', function (Argument $arg) {
$arg->setDefaultValue(20);
});
$schema->addQuery($countriesQuery);