Extending GraphQL
Adding Fields
New fields can be added to the GraphQL schema, on any object type. This can be used to register a field on a post type object, the global media type, or even an ACF field group. When you need to add a new field, you can find the object type name using the GraphQL IDE.
Add a field to a Type in the GraphQL Schema:
register_graphql_field(string $type_name, string $field_name, array $config);$type_name(string): The name of the GraphQL Type in the Schema to register the field to$field_name(string): The name of the field. Should be unique to the Type the field is being registered to.$config(array): Configuration for the field$type(string | array): The name of the GraphQL Type the field will return. The resolve function must return this type. For non-null fields:'type' => [ 'non_null' => 'TypeName' ]For listOf fields:'type' => [ 'list_of' => 'TypeName' ]$description(string): Description of the field. This will be used to self-document the schema and should describe to clients how the field should be used.$resolve(function): Function that will execute when the field is asked for in a query.
Adding Object Types
When adding a new field that should contain subfields, you’ll also want to register an object type.
Examples
Example: Adding svgContent to MediaItem:
The below code snippet will add an svgContent to all files and images in GraphQL, allowing you to grab raw SVG contents from SVG files. If the file isn’t an SVG, then the result will be null.
add_filter('graphql_register_types', function () {
register_graphql_field('MediaItem', 'svgContent', [
'type' => 'String',
'description' => 'The raw SVG content of the media item, if applicable.',
'resolve' => function ($mediaItem) {
// Get the full file path of the attachment
$filePath = get_attached_file($mediaItem->ID);
// If the file is an SVG, load the contents
if (preg_match('/\.svg$/i', $filePath) && file_exists($filePath)) {
// Return them
return file_get_contents($filePath);
}
// Otherwise, return null
return null;
}
]);
});Example: Adding a relationship from one post-type to another
The below code snippet will add a film field on the Session post type, which returns the parent post (if any).
When returning a post object, the post must be wrapped in new \WPGraphQL\Model\Post($post) to ensure that subfields can be properly selected.
add_filter('graphql_register_types', function () {
register_graphql_field("Session", "film", [
"type" => "Film",
"resolve" => function ($root) {
$parent = get_post_parent($root->ID);
if ($parent) {
return new \WPGraphQL\Model\Post($parent);
}
return null;
}
]);
});Example: Adding breadcrumbs to all post types
// Set up a default filter for handling breadcrumbs for post-types
add_filter('ed_post_breadcrumbs', function ($breadcrumbs, $post) {
if ($post->post_type == "page") {
$ancestors = array_reverse(get_ancestors($post->ID, 'page', 'post_type'));
foreach ($ancestors as $ancestor_id) {
$ancestor = get_post($ancestor_id);
$breadcrumbs[] = [
'title' => $ancestor->post_title,
'uri' => get_permalink($ancestor),
'active' => false,
];
}
}
$breadcrumbs[] = [
'title' => $post->post_title,
'uri' => get_permalink($post),
'active' => true,
];
return $breadcrumbs;
}, 0, 2);
// Add other post types
add_filter('ed_post_breadcrumbs', function ($breadcrumbs, $post) {
if ($post->post_type == "project") {
$breadcrumbs[] = [
'title' => 'Our Projects',
'uri' => '/work',
'active' => false
];
}
return $breadcrumbs;
}, 10, 2);
add_action('graphql_register_types', function () {
// Register a 'Breadcrumb' object type
register_graphql_object_type('Breadcrumb', [
'description' => 'A breadcrumb',
'fields' => [
'title' => [
'type' => 'String',
'description' => 'The title of the breadcrumb',
],
'uri' => [
'type' => 'String',
'description' => 'The URI of the breadcrumb',
],
'active' => [
'type' => 'Bool',
'description' => 'Whether the breadcrumb is active',
],
'back' => [
'type' => 'Bool'
]
],
]);
// Register a 'breadcrumb' field on all post types
register_graphql_field('ContentNode', 'breadcrumbs', [
'type' => ['list_of' => 'Breadcrumb'],
'resolve' => function ($root) {
$post = get_post($root->ID);
// Use a filter to collect breadcrumbs
$breadcrumbs = apply_filters('ed_post_breadcrumbs', [], $post);
return $breadcrumbs;
}
]);
});