Thanks @MichalKleiner
@Anthony van Beek There's a file type provided for you. See graphql/_config/assets.yml
nice, didn’t know about that.. it exposes a bit more than the URL but it’s still a bunch of strings 😄
Getting this error now, reverted all my changes and flushed, won't go away.
'Hero' => $this->manager->getType(StaticSchema::inst()->typeName(File::class))
Awesome that removed my type error
kind of a shit api
hahaha, now got this
"errors": [ { "message": "Type 'SilverStripe_Assets_File' is not a registered GraphQL type",
ignore indents
In my Course class I define Hero
as
'Hero' => Image::class, );
Shoudl be SilverStripe_Assets_Storage_File
I changed it to 'Hero' => $this->manager->getType(StaticSchema::inst()->typeName(DBFile::class)),
yes that's right
now I get
POST /graphql/ Line 172 in /vagrant/vendor/silverstripe/graphql/src/TypeCreator.php Source 163 * or resolveField(). 164 * 165 * @param string $name Name of the field 167 * @return callable|null The callback, or null if there is no field resolver 168 */ 169 protected function getFieldResolver($name, $field) 170 { 171 // Preconfigured method 173 return $field['resolve']; 174 } 175 $candidateMethods = [ 177 'resolveField', 178 ];
'Hero' => ['type' => $this->manager... ]
Ok so I got 'Hero' => ['type' => $this->manager->getType(StaticSchema::inst()->typeName(DBFile::class))],
back to this error
[Notice] Undefined index: type POST /graphql/ Line 142 in /vagrant/vendor/webonyx/graphql-php/src/Type/Definition/FieldDefinition.php Source 133 } 134 135 /** 136 * FieldDefinition constructor. 137 * @param array $config 138 */ 140 { 141 $this->name = $config['name']; 142 $this->type = $config['type']; 146 148 $this->deprecationReason = isset($config['deprecationReason']) ? $config['deprecationReason'] : null;
So I assume I need to to add DBFile into my types
Did that now I got:
[Emergency] Uncaught InvalidArgumentException: "SilverStripe\Assets\Storage\DBFile" is not a DataObject subclass Line 77 in /vagrant/vendor/silverstripe/graphql/src/Scaffolding/Traits/DataObjectTypeTrait.php Source 68 if (!$class) { 69 throw new InvalidArgumentException("Missing class provided"); 70 } 71 73 throw new InvalidArgumentException("Non-existent classname \"{$class}\""); 74 } 75 77 throw new InvalidArgumentException("\"{$class}\" is not a DataObject subclass"); 78 } 79 80 $this->dataObjectClass = $class; 81 return $this; 82 } 83 }
It should be added in SchemaScaffolder::registerFixedTypes
, no?
or are you not using any scaffolding?
I’ve got a graphql.yml with scaffolding
huh.. can you debug why SchemaScaffolder isn't adding it in registerFixedTypes?
should I add SchemaScaffolder::registerFixedTypes
somewhere?
no, it should be called in SchemaScaffolder::addToManager
.. can you debug that?
I’ve added
public function addToManager(Manager $manager) { dump('running manager'); dump($manager);
am getting it run 3 times
$this->registerFixedTypes($manager); is run 3 times
race condition
Your type creator is run before that is called
i wonder if you can put your fields in a closure
just for fun, try wrapping the return statement for your fields()
function in a closure. I can't remember if that's allowed or not.
function { return ['ID' => ['type' ...] ] }
etc..
will do
mmmmm this is currently my function
public function fields() { $courseConnection = Connection::create('Topics') ->setConnectionType(function () { }) ->setDescription('A list of the Topics') ->setSortableFields(['ID', 'Title']); return [ 'ID' => ['type' => Type::nonNull(Type::id())], 'Title' => ['type' => Type::string()], 'Estimate' => ['type' => Type::string()], 'Audience' => ['type' => Type::string()], 'Content' => ['type' => Type::string()], 'URLSegment' => ['type ' => Type::string()], 'Topics' => [ 'type' => $courseConnection->toType(), 'args' => $courseConnection->args(), return $courseConnection->resolveList( $object->Topics(), $args, $context ); } ] ]; }
This is what my graphql.yml file looks like :
SilverStripe\GraphQL\Manager: schemas: default: types: Course: myProject\CourseTypeCreator ... mutations: ... queries: ... scaffolding: types: Page: ... myProject\Topic: ... typeNames: DNADesign\Elemental\Models\BaseElement: Block DNADesign\Elemental\Models\ElementalArea: ElementalArea myProject\Topic: Topic ...
so my fields function was already as you suggested
no, I mean return a function instead of an array
return function () { return [ 'ID' => ['type' => Type::nonNull(Type::id())],
was afk for ☕ trying now
Error: Course fields must be an object with field names as keys or a function which returns such an object. at invariant (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:25910:12) at defineFieldMap (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26708:28) at GraphQLObjectType.getFields (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26674:45) at http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26364:28 at typeMapReducer (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26376:8) at http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26374:23 at http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26365:30 at typeMapReducer (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26376:8) at typeMapReducer (http://sorted-website.local:8080/resources/vendor/silverstripe/graphql-devtools/client/dist/graphiql.js?m=1557276366:26344:13)
I wonder if that registerFixedTypes needs to be abstracted out of SchemaScaffolder, since it applies to non-scaffolded schema, too.
it's almost like fixed_types
needs to be a config property of Manager, not SchemaScaffolder.
:) ¯_(ツ)_/¯
Well I could just scaffold the Course which worked previously
Is there a reason you're using the typecreator in lieu of scaffolding? I know there are many, but I'm curious what your reasoning is here, because it seems straightforward.
I was looking at adding in my own custom fields to the graphql response.
eg. I want to calculate the progress of a course and add it as a field into the Course response
Computed properties work in the scaffolder, though.. getCourseProgress()
can be declared as fields: { CourseProgress }
Thanks mil for all your help @unclecheese
oh did it work?
Yesssss!
wow! glad I could help!
So am I 😂
The problem that lead me down that rabbit hole is that fields: '*'
doesn’t pick up the computed properties.
ah, right
😂
i often wonder if we could expose those through docblocks
What is the best way to get the currently logged in user in my model?
Security::getCurrentUser();
works in dev/graphiqp
but not from my SPA which uses token auth.
Nevermind got sorted. 🙂
Has anyone used extra_fields with GraphQL?
Not yet… we used custom resolvers and custom type creators, so I imagine it wouldn’t be a problem there. Not sure about the scaffolder.
Yeah think you need a custom type as there's no way to define the joined fields otherwise