mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-19 16:06:32 +02:00
c1cda2b113
* DOCS: Add new graphql 4 docs * Reorganise docs * Docs done * Basic graphql index page * TOC for getting started * show folders on graphql index page * Add middleware note * Docs update * Update docs to reflect flushless schema * Docs updates * Docs for getByLink * Query caching docs * Docs on nested operations * update docs for new graphql dev admin * Docs for configurable operations * Replace readSiteTrees with readPages * Schema defaults docs * Docs for inherited plugins * Docs for customising * * Docs for field whitelisting * Change whitelist word * New docs on modelConfig * Document dev/build extension * Document default/global plugins * Document new input type fields config * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Note about when procedural schema gets built * Fix link * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Note about plugins in custom queries * DOCS Note about filter and custom resolvers * DOCS Note about canview paging * DOCS Updated guidance on _extend See https://github.com/silverstripe/silverstripe-graphql/issues/296 * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Pre-release warning Co-authored-by: Ingo Schommer <ingo@silverstripe.com> Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> Co-authored-by: Ingo Schommer <me@chillu.com>
118 lines
3.8 KiB
Markdown
118 lines
3.8 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:
|
|
|
|
```yaml
|
|
SilverStripe\Core\Injector\Injector:
|
|
SilverStripe\GraphQL\Schema\Registry\SchemaModelCreatorRegistry:
|
|
constructor:
|
|
dataobject: '%$SilverStripe\GraphQL\Schema\DataObject\ModelCreator'
|
|
```
|
|
|
|
### Further reading
|
|
|
|
[CHILDREN]
|