PHP Lighthouse 从 FieldResolver 中的根查询获取参数

Posted

技术标签:

【中文标题】PHP Lighthouse 从 FieldResolver 中的根查询获取参数【英文标题】:PHP Lighthouse get parameter from root query in FieldResolver 【发布时间】:2021-03-28 07:38:40 【问题描述】:

我有以下查询设置:

extend type Query 
    positionGroups(quoteId: ID): [PositionGroup!]! @all 


type PositionGroup 
    ...
    positions: [Position!]!


type Position 
    ...
    amount: Amount @amountEnhancedWithQuoteAmountInfo

Position 中的 amount 通常返回默认值,但如果我们处于特定 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 的查询内容。

【问题讨论】:

【参考方案1】:

我自己构建了一个解决方案,我创建了一个PassAlongDirective,它将传递参数或字段给孩子:

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"])

【讨论】:

以上是关于PHP Lighthouse 从 FieldResolver 中的根查询获取参数的主要内容,如果未能解决你的问题,请参考以下文章

如何在lighthouse graphql laravel中获取自定义指令参数?

尝试将 laravel lighthouse-php 与 Roadrunner Server 一起使用时遇到间歇性错误

使用 Lighthouse 发送标头

web 性能优化( Lighthouse 和 performance ):从实际项目入手,如何监测性能问题如何解决

使用 Laravel Lighthouse 在 Laravel 7 中出现 CORS 错误

JS周刊#402 - Babel与TypeScript联姻,如何让Vue App Lighthouse获得满分,JS计时器之旅