You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This library contains the necessary primitives to handle directives and customize schema building, and i do not think it should do anything more opinionated.
Since you have a type loader for buildschema, I was expecting the lib would do something for any node kind or a pointer of how to do it. For other people that one day may find themselves here, I solved it by parsing the AST normally, them modifying it using Visitor.
If I may suggest something, it would be interesting to have a callback for enter/leave like Visitor already in buildSchema.
Of course! The way I implemented the class loader I described above was more or less like this (and I am still struggling to find out how to replace the Type class on the fields):
$ast = \GraphQL\Language\Parser::parse($data);
Visitor::visit($this->ast, [
NodeKind::SCALAR_TYPE_DEFINITION => function ($node) {
// some code to read the directives and map the $node->name->value to my classreturnnull;
}
]);
$schemaBuilder = new \GraphQL\Utils\BuildSchema(ast);
$schema = $schemaBuilder->buildSchema();
A visitor is what I expected the callback from BuildSchema to do -- it's not clear to me from the docs what exactly it does, is it only called for types?
Again, the use cases is what is being done in the tests. You build a schema manually in the VariablesTest with the custom class:
but from what I understood from your answer it's hard to do that from a graphql description. Lighthouse seems to reimplement the schema builder completely. If there was a Visitor-like callback for BuildSchema, I could have a callback that could easily customize the creation of the Schema object, replacing the generic Scalar type for a MyCustomClass().
I might have understood this incorrectly. But my understanding is that:
You are trying to define your schema with SDL
Define a class for your custom scalar type using a directive
Technically this should be probably done by allowing custom typeLoader for the buildSchema. But in the meantime I think there is an existing workaround - you can replace the typeLoader and use it to replace CustomScalarType with your custom class.
Something along the lines should probably work (didn't check though):
$ast = \GraphQL\Language\Parser::parse($sdl);
$schemaBuilder = new \GraphQL\Utils\BuildSchema($ast);
$schema = $schemaBuilder->buildSchema();
$originalTypeLoader = $schema->getConfig()->typeLoader;
$schema->getConfig()->typeLoader = function($typeName) use ($originalTypeLoader) {
$type = $originalTypeLoader($typeName);
if ($typeinstanceof \GraphQL\Type\Definition\CustomScalarType) {
$directives = $type->astNode->directives;
// Look for your `@scalar` directive in $directives and return your custom class instead$customClass = findMyScalarClassName($directives);
returnnew$customClass($type->config);
}
return$type;
}
# used to specify the desired class to execute for a custom scalar directive@scalar(class: String!) onSCALAR# add the directive to each custom scalarscalarEmail@scalar(class: "Compwright\\GraphqlScalars\\Email")
If multiple decorators are needed to implement various other things, they could be pipelined together using something like https://github.com/thephpleague/pipeline.
An official way to do this without relying on directives and type decorators would be great!
Activity
spawnia commentedon Jun 25, 2020
What you are trying to do is quite tricky and requires deeply modifying the schema build process. Check out https://github.com/nuwave/lighthouse/tree/master/src/Schema for an example of how this can be achieved.
This library contains the necessary primitives to handle directives and customize schema building, and i do not think it should do anything more opinionated.
brunobg commentedon Jun 25, 2020
Since you have a type loader for
buildschema, I was expecting the lib would do something for any node kind or a pointer of how to do it. For other people that one day may find themselves here, I solved it by parsing the AST normally, them modifying it using Visitor.If I may suggest something, it would be interesting to have a callback for enter/leave like Visitor already in buildSchema.
spawnia commentedon Jun 25, 2020
Can you elaborate? What new use cases would this enable/how does it make existing use cases easier?
brunobg commentedon Jun 25, 2020
Of course! The way I implemented the class loader I described above was more or less like this (and I am still struggling to find out how to replace the Type class on the fields):
A visitor is what I expected the callback from
BuildSchemato do -- it's not clear to me from the docs what exactly it does, is it only called for types?Again, the use cases is what is being done in the tests. You build a schema manually in the VariablesTest with the custom class:
graphql-php/tests/Executor/VariablesTest.php
Line 132 in 1f0ec24
but from what I understood from your answer it's hard to do that from a graphql description. Lighthouse seems to reimplement the schema builder completely. If there was a Visitor-like callback for BuildSchema, I could have a callback that could easily customize the creation of the
Schemaobject, replacing the generic Scalar type for a MyCustomClass().Thank you for the interest and prompt replies.
vladar commentedon Jun 26, 2020
I might have understood this incorrectly. But my understanding is that:
Technically this should be probably done by allowing custom
typeLoaderfor thebuildSchema. But in the meantime I think there is an existing workaround - you can replace thetypeLoaderand use it to replaceCustomScalarTypewith your custom class.Something along the lines should probably work (didn't check though):
Obviously just a workaround but it should work?
brunobg commentedon Jun 26, 2020
Thank you very much, it seems that will work perfectly.
brunobg commentedon Jun 26, 2020
Ahn, @vladar, sorry for the endless pestering, but besides the bug from #683, it seems that this does not replace types in fields. For example:
calls your
typeLoaderonly with aObjectType, and when I traverse the AST theFieldDefinition$typeis stillCustomScalarType.Perhaps I'm missing something and it only lazy loads?
Could I use a
SchemaExtenderto do this, overridingextendCustomScalarType?vladar commentedon Jun 29, 2020
Good catch.
typeLoaderis only partially useful indeed.Reopening since I think this is a typical use-case (providing custom scalar type class) so we should provide a way to do it in this library.
compwright commentedon Jan 30, 2024
It took a heck of a lot of work getting here, but I managed to solve this using a $typeConfigDecorator:
You'll need this in your schema:
Then when loading the schema:
If multiple decorators are needed to implement various other things, they could be pipelined together using something like https://github.com/thephpleague/pipeline.
An official way to do this without relying on directives and type decorators would be great!
P.S. this solution is included in https://github.com/compwright/graphql-php-scalars.
Add \`types\` parameter to BuildSchema for injecting pre-built type i…
spawnia commentedon Mar 14, 2026
I am attempting to solve this with #1872, looking for feedback.