Skip to content

Commit 0d54dd1

Browse files
committed
Improve default field resolver performance
1 parent 8ac73c8 commit 0d54dd1

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

UPGRADE-0.13.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
UPGRADE FROM 0.12 to 0.13
2+
=======================
3+
4+
# Table of Contents
5+
6+
- [Improve default field resolver](#improve-default-field-resolver)
7+
8+
### Improve default field resolver
9+
10+
Stop using internally `symfony/property-access` package
11+
since it was a bottleneck to performance for large schema.
12+
13+
Array access and camelize getter are supported but isser, hasser,
14+
jQuery style (e.g. `last()`) and "can" property accessors
15+
are no more supported out-of-the-box,
16+
please implement a custom resolver if these accessors are needed.
17+
18+
Globally:
19+
20+
```yaml
21+
overblog_graphql:
22+
definitions:
23+
default_resolver: 'App\GraphQL\CustomResolver::defaultFieldResolver'
24+
```
25+
26+
[see default field resolver for more details](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver)
27+
28+
Per Type:
29+
30+
```yaml
31+
MyType:
32+
type: object
33+
config:
34+
resolveField: 'App\GraphQL\MyTypeResolver::defaultFieldResolver'
35+
fields:
36+
name: {type: String}
37+
email: {type: String}
38+
```
39+
40+
[see default Field Resolver per type for more details](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver-per-type)

composer.json

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
"symfony/expression-language": "^4.3 || ~5.0",
3838
"symfony/framework-bundle": "^4.3 || ~5.0",
3939
"symfony/options-resolver": "^4.3 || ~5.0",
40-
"symfony/property-access": "^4.3 || ~5.0",
4140
"webonyx/graphql-php": "^0.13.5"
4241
},
4342
"replace": {

src/Resolver/Resolver.php

+16-31
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,9 @@
55
namespace Overblog\GraphQLBundle\Resolver;
66

77
use GraphQL\Type\Definition\ResolveInfo;
8-
use Symfony\Component\PropertyAccess\PropertyAccess;
9-
use Symfony\Component\PropertyAccess\PropertyAccessor;
108

119
class Resolver
1210
{
13-
/** @var PropertyAccessor */
14-
private static $accessor;
15-
1611
public static function defaultResolveFn($objectOrArray, $args, $context, ResolveInfo $info)
1712
{
1813
$fieldName = $info->fieldName;
@@ -24,44 +19,34 @@ public static function defaultResolveFn($objectOrArray, $args, $context, Resolve
2419
public static function valueFromObjectOrArray($objectOrArray, $fieldName)
2520
{
2621
$value = null;
27-
$index = \sprintf('[%s]', $fieldName);
28-
29-
if (self::isReadable($objectOrArray, $index)) {
30-
$value = self::getAccessor()->getValue($objectOrArray, $index);
31-
} elseif (\is_object($objectOrArray) && self::isReadable($objectOrArray, $fieldName)) {
32-
$value = self::getAccessor()->getValue($objectOrArray, $fieldName);
22+
if (\is_array($objectOrArray) && isset($objectOrArray[$fieldName])) {
23+
$value = $objectOrArray[$fieldName];
24+
} elseif (\is_object($objectOrArray)) {
25+
if (null !== $getter = self::guessObjectMethod($objectOrArray, $fieldName, 'get')) {
26+
$value = $objectOrArray->$getter();
27+
} elseif (isset($objectOrArray->$fieldName)) {
28+
$value = $objectOrArray->$fieldName;
29+
}
3330
}
3431

3532
return $value;
3633
}
3734

3835
public static function setObjectOrArrayValue(&$objectOrArray, $fieldName, $value): void
3936
{
40-
$index = \sprintf('[%s]', $fieldName);
41-
42-
if (self::isWritable($objectOrArray, $index)) {
43-
self::getAccessor()->setValue($objectOrArray, $index, $value);
44-
} elseif (\is_object($objectOrArray) && self::isWritable($objectOrArray, $fieldName)) {
45-
self::getAccessor()->setValue($objectOrArray, $fieldName, $value);
37+
if (\is_array($objectOrArray)) {
38+
$objectOrArray[$fieldName] = $value;
39+
} elseif (\is_object($objectOrArray)) {
40+
$objectOrArray->$fieldName = $value;
4641
}
4742
}
4843

49-
private static function isReadable($objectOrArray, $indexOrProperty)
50-
{
51-
return self::getAccessor()->isReadable($objectOrArray, $indexOrProperty);
52-
}
53-
54-
private static function isWritable($objectOrArray, $indexOrProperty)
55-
{
56-
return self::getAccessor()->isWritable($objectOrArray, $indexOrProperty);
57-
}
58-
59-
private static function getAccessor()
44+
private static function guessObjectMethod($object, string $fieldName, string $prefix): ?string
6045
{
61-
if (null === self::$accessor) {
62-
self::$accessor = PropertyAccess::createPropertyAccessor();
46+
if (\is_callable([$object, $method = $prefix.\str_replace(' ', '', \ucwords(\str_replace('_', ' ', $fieldName)))])) {
47+
return $method;
6348
}
6449

65-
return self::$accessor;
50+
return null;
6651
}
6752
}

0 commit comments

Comments
 (0)