mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-19 16:06:32 +02:00
117 lines
3.7 KiB
Markdown
117 lines
3.7 KiB
Markdown
---
|
|
title: Adding a custom model
|
|
summary: Add a new class-backed type beyond DataObject
|
|
---
|
|
# Extending the Schema
|
|
|
|
[CHILDREN asList]
|
|
|
|
[alert]
|
|
You are viewing docs for a pre-release version of silverstripe/graphql (4.x).
|
|
Help us improve it by joining #graphql on the [Community Slack](https://www.silverstripe.org/blog/community-slack-channel/),
|
|
and report any issues at [github.com/silverstripe/silverstripe-graphql](https://github.com/silverstripe/silverstripe-graphql).
|
|
Docs for the current stable version (3.x) can be found
|
|
[here](https://github.com/silverstripe/silverstripe-graphql/tree/3)
|
|
[/alert]
|
|
|
|
## Adding a custom model
|
|
|
|
The only point of contact the `silverstripe-graphql` schema has with
|
|
Silverstripe specifically is through the `DataObjectModel` adapter
|
|
and its associated plugins. This is important, because it means you
|
|
can plug in any schema-aware class as a model, and it will be afforded
|
|
all the same features as DataObjects.
|
|
|
|
It is, however, hard to imagine a model-driven type that isn't
|
|
related to an ORM, so we'll keep this section simple and just describe
|
|
what the requirements are rather than think up an outlandish example
|
|
of what a non-DataObject model might be.
|
|
|
|
### SchemaModelInterface
|
|
|
|
Models must implement the `SchemaModelInterface`, which has some
|
|
hefty requirements. Let's walk through them:
|
|
|
|
* `getIdentifier(): string`: A unique identifier for this model type,
|
|
e.g. 'DataObject'
|
|
* `hasField(string $fieldName): bool`: Return true if `$fieldName` exists
|
|
on the model
|
|
* `getTypeForField(string $fieldName): ?string`: Given a field name,
|
|
infer the type. If the field doesn't exist, return `null`
|
|
* `getTypeName(): string`: Get the name of the type (i.e. based on
|
|
the source class)
|
|
* `getDefaultResolver(?array $context = []): ResolverReference`:
|
|
Get the generic resolver that should be used for types that are built
|
|
with this model.
|
|
* `getSourceClass(): string`: Get the name of the class that builds
|
|
the type, e.g. `MyDataObject`
|
|
* `getAllFields(): array`: Get all availble fields on the object
|
|
* `getModelField(string $fieldName): ?ModelType`: For nested fields.
|
|
If a field resolves to another model (e.g. has_one), return that
|
|
model type.
|
|
|
|
In addition, models may want to implement:
|
|
|
|
* `OperationProvider` (if your model creates operations, like
|
|
read, create, etc)
|
|
* `DefaultFieldsProvider` (if your model provides a default list
|
|
of fields, e.g. `id`)
|
|
* `DefaultPluginProvider` (if your model can supply a default set
|
|
of plugins, e.g. `default_plugins` on `DataObjectModel`)
|
|
|
|
This is all a lot to take in out of context. A good exercise would be
|
|
to look through how `DataObjectModel` implements all these methods.
|
|
|
|
### SchemaModelCreatorInterface
|
|
|
|
Given a class name, create an instance of `SchemaModelInterface`.
|
|
This layer of abstraction is necessary because we can't assume that
|
|
all `SchemaModelInterfaces` will accept a class name in their
|
|
constructors.
|
|
|
|
Implementors of this interface just need to be able to report
|
|
whether they apply to a given class and create a model given a
|
|
class name.
|
|
|
|
Look at the DataObjectModel implementation:
|
|
|
|
```php
|
|
class ModelCreator implements SchemaModelCreatorInterface
|
|
{
|
|
use Injectable;
|
|
|
|
/**
|
|
* @param string $class
|
|
* @return bool
|
|
*/
|
|
public function appliesTo(string $class): bool
|
|
{
|
|
return is_subclass_of($class, DataObject::class);
|
|
}
|
|
|
|
/**
|
|
* @param string $class
|
|
* @return SchemaModelInterface
|
|
*/
|
|
public function createModel(string $class): SchemaModelInterface
|
|
{
|
|
return DataObjectModel::create($class);
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
### Registering your model creator
|
|
|
|
Just add it to the registry:
|
|
|
|
**app/_graphql/config.yml
|
|
```yaml
|
|
modelCreators:
|
|
- 'SilverStripe\GraphQL\Schema\DataObject\ModelCreator'
|
|
```
|
|
|
|
### Further reading
|
|
|
|
[CHILDREN]
|