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。 不过有更好的方法吗?

注意:PositionQuote 没有任何关系,但是,在引用的上下文中,我想在本质上向它添加一些额外的信息。因此,如果用户不提供 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"])