PHP Lighthouse 从 FieldResolver 中的根查询获取参数
PHP Lighthouse get parameter from root query in FieldResolver
我有以下查询设置:
extend type Query {
positionGroups(quoteId: ID): [PositionGroup!]! @all
}
type PositionGroup {
...
positions: [Position!]!
}
type Position {
...
amount: Amount @amountEnhancedWithQuoteAmountInfo
}
Position
中的 amount
通常是 returns 的默认值,但是如果我们在特定的上下文中 quote
它可能会改变。
这就是 AmountEnhancedWithQuoteAmountInfoDerictive
应该做的。
所以在 AmountEnhancedWithQuoteAmountInfoDerictive
里面我需要 quoteId
值(如果有的话)。
然后我可以应用一些额外的逻辑从数据库中获取特定于报价的金额。
如果没有给出 quoteId
,我不需要做任何额外的事情。
我的指令是这样的:
class AmountEnhancedWithLBHQuoteAmountInfoDirective extends BaseDirective implements FieldResolver
{
/**
* @inheritDoc
*/
public function resolveField(FieldValue $fieldValue)
{
$this->$fieldValue->setResolver(function ($root, $args, GraphQLContext $context, ResolveInfo $resolveInfo) {
$value = $root->amount;
$something->quoteId; // What should this be?
// Change $value based on the quote
return $value;
});
return $fieldValue;
}
}
$root
变量就是我的Position
,其他参数里也找不到quoteId
那么有没有办法访问那里的quoteId
?
我能想到的一种方法是为每个部分编写自定义查询,然后简单地传递 quoteId
。
不过有更好的方法吗?
注意:Position
与 Quote
没有任何关系,但是,在引用的上下文中,我想在本质上向它添加一些额外的信息。因此,如果用户不提供 quoteId
参数,就无法知道 Quote
查询的内容。
我自己构建了一个解决方案,我创建了一个 PassAlongDirective
,它会将参数或字段传递给 children:
class PassAlongDirective extends BaseDirective implements FieldMiddleware, DefinedDirective
{
public static function definition(): string
{
return 'Passes along parameters to children.';
}
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue
{
$resolver = $fieldValue->getResolver();
$fieldsToPassAlong = $this->directiveArgValue('fields', []);
$fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($resolver, $fieldsToPassAlong) {
$result = $resolver($root, $args, $context, $resolveInfo);
foreach ($fieldsToPassAlong as $field) {
$value = $args[$field] ?? $root->{$field} ?? null;
if ($value) {
$this->passAlongTo($result, $field, $value);
}
}
return $result;
});
return $next($fieldValue);
}
private function passAlongTo($result, $field, $value)
{
if ($result instanceof Collection || $result instanceof Paginator) {
foreach ($result as $item) {
$this->setField($item, $field, $value);
}
} else {
$this->setField($result, $field, $value);
}
}
private function setField($item, $field, $value)
{
$item->{$field} = $value;
}
}
它可以像这样使用:
positionGroups(quoteId: ID): [PositionGroup!]! @all @passAlong(fields: ["quoteId"])
我有以下查询设置:
extend type Query {
positionGroups(quoteId: ID): [PositionGroup!]! @all
}
type PositionGroup {
...
positions: [Position!]!
}
type Position {
...
amount: Amount @amountEnhancedWithQuoteAmountInfo
}
Position
中的 amount
通常是 returns 的默认值,但是如果我们在特定的上下文中 quote
它可能会改变。
这就是 AmountEnhancedWithQuoteAmountInfoDerictive
应该做的。
所以在 AmountEnhancedWithQuoteAmountInfoDerictive
里面我需要 quoteId
值(如果有的话)。
然后我可以应用一些额外的逻辑从数据库中获取特定于报价的金额。
如果没有给出 quoteId
,我不需要做任何额外的事情。
我的指令是这样的:
class AmountEnhancedWithLBHQuoteAmountInfoDirective extends BaseDirective implements FieldResolver
{
/**
* @inheritDoc
*/
public function resolveField(FieldValue $fieldValue)
{
$this->$fieldValue->setResolver(function ($root, $args, GraphQLContext $context, ResolveInfo $resolveInfo) {
$value = $root->amount;
$something->quoteId; // What should this be?
// Change $value based on the quote
return $value;
});
return $fieldValue;
}
}
$root
变量就是我的Position
,其他参数里也找不到quoteId
那么有没有办法访问那里的quoteId
?
我能想到的一种方法是为每个部分编写自定义查询,然后简单地传递 quoteId
。
不过有更好的方法吗?
注意:Position
与 Quote
没有任何关系,但是,在引用的上下文中,我想在本质上向它添加一些额外的信息。因此,如果用户不提供 quoteId
参数,就无法知道 Quote
查询的内容。
我自己构建了一个解决方案,我创建了一个 PassAlongDirective
,它会将参数或字段传递给 children:
class PassAlongDirective extends BaseDirective implements FieldMiddleware, DefinedDirective
{
public static function definition(): string
{
return 'Passes along parameters to children.';
}
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue
{
$resolver = $fieldValue->getResolver();
$fieldsToPassAlong = $this->directiveArgValue('fields', []);
$fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($resolver, $fieldsToPassAlong) {
$result = $resolver($root, $args, $context, $resolveInfo);
foreach ($fieldsToPassAlong as $field) {
$value = $args[$field] ?? $root->{$field} ?? null;
if ($value) {
$this->passAlongTo($result, $field, $value);
}
}
return $result;
});
return $next($fieldValue);
}
private function passAlongTo($result, $field, $value)
{
if ($result instanceof Collection || $result instanceof Paginator) {
foreach ($result as $item) {
$this->setField($item, $field, $value);
}
} else {
$this->setField($result, $field, $value);
}
}
private function setField($item, $field, $value)
{
$item->{$field} = $value;
}
}
它可以像这样使用:
positionGroups(quoteId: ID): [PositionGroup!]! @all @passAlong(fields: ["quoteId"])