Last active
October 11, 2019 14:12
-
-
Save n8jadams/54e3c5d29771c3a2875cf91925ff0a12 to your computer and use it in GitHub Desktop.
GraphQLQueryChecker. A PHP Class that checks if a field is requested in the query. I've used this in production with webonyx/graphql-php v0.9.14 for more than a year.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Instructions: | |
* In an Object Resolve function, use the fourth argument ($info) | |
* | |
* Example usage: | |
* | |
* $fieldInQuery = GraphQLQueryChecker::isFieldInQuery('some.nested.fieldname', $info); | |
* | |
* If the query looks like this: | |
* | |
* query() { | |
* myObject { | |
* something | |
* some { | |
* nested { | |
* fieldname | |
* } | |
* } | |
* } | |
* } | |
* | |
* It will be true. | |
* | |
* If it looks like this: | |
* query() { | |
* myObject { | |
* something | |
* some { | |
* nested { | |
* field | |
* } | |
* } | |
* } | |
* } | |
* | |
* It will return false. | |
* | |
* This is useful if you have some fields that are expensive to calculate | |
* and want to optimize if those fields aren't requested. | |
* | |
*/ | |
class GraphQLQueryChecker | |
{ | |
public static $found = false; | |
public static $fields = []; | |
// If you pass the $info field from a GraphQL resolve function, we can | |
// recursively check the body of the passed query to determine if a | |
// field is present. $fieldPath are dot separated fields. Ex: edges.node.id | |
public static function isFieldInQuery($fieldPath, $info) { | |
self::$fields = explode('.', $fieldPath); | |
self::$found = false; | |
foreach($info->fieldNodes as $fn) { | |
if(!empty($fn->selectionSet)) { | |
self::recursiveCheck(self::$fields[0], $fn->selectionSet->selections); | |
} | |
} | |
return self::$found; | |
} | |
private static function recursiveCheck($field, $selections) { | |
foreach($selections as $selection) { | |
$nextField = self::getNextField($field); | |
if($selection->name->value === $field && $nextField === null) { | |
self::$found = true; | |
break; | |
} else if($selection->name->value === $field && !empty($selection->selectionSet)) { | |
self::recursiveCheck($nextField, $selection->selectionSet->selections); | |
break; | |
} else if(!empty($selection->selectionSet)) { | |
self::recursiveCheck($field, $selection->selectionSet->selections); | |
} | |
} | |
} | |
private static function getNextField($prevField) { | |
for($i = 0; $i<count(self::$fields); $i++) { | |
if($prevField === self::$fields[$i]) { | |
return self::$fields[$i + 1]; | |
} | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment