【问题标题】:What is the correct way of using @scope directive?使用@scope 指令的正确方法是什么?
【发布时间】:2021-03-03 01:14:40
【问题描述】:

我无法理解 @scope 指令的工作原理。当我将指令添加到查询定义并给出 IsOwner:true Lighthouse 将其添加到范围时,但当我将其更改为 IsOwner:false 时问题就开始了。 Lighthouse 仍将范围应用于查询。只有当我从查询中删除 IsOwner 参数时 Lighthouse 才不会应用范围。

我的查询定义如下;

listings(IsOwner: Boolean @scope(name:"IsOwner"), where: _ @whereConditions(columnsEnum: "ListingColumn"), orderBy: _ @orderBy(columnsEnum: "ListingColumn")) : [Listing!]! @paginate(maxCount: 50 defaultCount: 10)

实际查询如下;

query ($min_lng:Float!, $min_lat:Float!, $max_lng:Float!, $max_lat:Float!, $first:Int, $page:Int, $withPaginatorInfo:Boolean!, $withListingImages:Boolean!, $withListingMeta:Boolean!, $withListingViews:Boolean!, $withListingActions:Boolean!, $withListingNotes:Boolean!, $withListingReminders:Boolean!, $withListingViewUser:Boolean = false, $conditions: ListingsWhereWhereConditions, $orderBy: [ListingsOrderByOrderByClause!]) {
listings(
    bbox: {
        min_lng: $min_lng
        min_lat: $min_lat
        max_lng: $max_lng
        max_lat: $max_lat
    }
    IsOwner: false
    where:  $conditions
    orderBy: $orderBy
    first: $first
    page: $page
) {
    data {
        ...listingFields
    }
    paginatorInfo @include(if: $withPaginatorInfo) {
        currentPage
        lastPage
    }
}

}

Model scope it like following;

    public function scopeIsOwner($query)
    {
        return $query->join('listing_user', 'listing_user.listing_id', '=', 'listings.id')->where('listing_user.user_id', Auth::user()->id);
    }

*** 更新 ***

我在cmets之后想通了,我把模型范围改成如下

public function scopeIsOwner($query, $isEnabled)
    {
        if ($isEnabled) {
            return $query->join('listing_user', 'listing_user.listing_id', '=', 'listings.id')->where('listing_user.user_id', Auth::user()->id);
        }

        return $query;
    }

我对下面的架构做了一些小改动,

listings(scopeIsOwner: Boolean @scope(name:"IsOwner"), bbox: BoundingBoxInput! @builder(method: "App\\GraphQL\\Builders\\BoundingBoxSearch@bbSearch"), where: _ @whereConditions(columnsEnum: "ListingColumn"), orderBy: _ @orderBy(columnsEnum: "ListingColumn")) : [Listing!]! @guard(with: ["api"]) @paginate(maxCount: 50 defaultCount: 10)

我的最终查询及其变量如下所示,

query ($min_lng:Float!, $min_lat:Float!, $max_lng:Float!, $max_lat:Float!, $first:Int, $page:Int, $withPaginatorInfo:Boolean!, $withListingImages:Boolean!, $withListingMeta:Boolean!, $withListingViews:Boolean!, $withListingActions:Boolean!, $withListingNotes:Boolean!, $withListingReminders:Boolean!, $withListingViewUser:Boolean = false, $scopeIsOwner:Boolean = false $conditions: ListingsWhereWhereConditions, $orderBy: [ListingsOrderByOrderByClause!]) {
    listings(
        bbox: {
            min_lng: $min_lng
            min_lat: $min_lat
            max_lng: $max_lng
            max_lat: $max_lat
        }
        scopeIsOwner: $scopeIsOwner
        where:  $conditions
        orderBy: $orderBy
        first: $first
        page: $page
    ) {
        data {
            ...listingFields
        }
        paginatorInfo @include(if: $withPaginatorInfo) {
            currentPage
            lastPage
        }
    }
}

变量;

{
  "min_lng": 29.0401317,
  "min_lat": 41.0028473,
  "max_lng": 29.0308512,
  "max_lat": 40.9916271,
  "withPaginatorInfo" : true,
  "first": 10,
  "page": 1,
  "withListingImages": false,
  "withListingMeta": false,
  "withListingViews": false,
  "withListingActions": false,
  "withListingNotes": false,
  "withListingReminders": false,
  "withListingViewUser": false,
  "conditions": {"AND": [{"column": "PRICE", "operator": "LTE","value": "190"}]},
  "orderBy": [{ "column": "TENURE_ID", "order": "DESC" }],
  "scopeIsOwner": false
}

正如你所理解的,当我对 scopeIsOwner 变量赋予 true 时,端点会启用范围并相应地操作查询。

【问题讨论】:

    标签: php laravel graphql laravel-lighthouse


    【解决方案1】:

    你误会了。见https://lighthouse-php.com/master/api-reference/directives.html#scope

    范围方法将接收客户端给定的参数值作为第二个参数。

    您的作用域应该对客户端传递的参数做出反应。

    【讨论】:

      【解决方案2】:

      Lighthouse 库中有一个错误。当参数存在而不检查值时添加范围。 ScopeDirective 类和handleBuilder 方法很简单

      public function handleBuilder($builder, $value)
          {
              $scope = $this->directiveArgValue('name');
      
              try {
                  return $builder->{$scope}($value);
              } catch (BadMethodCallException $exception) {
                  throw new DefinitionException(
                      $exception->getMessage()." in {$this->name()} directive on {$this->nodeName()} argument.",
                      $exception->getCode(),
                      $exception->getPrevious()
                  );
              }
          }
      

      我认为 $value 包含 true 或 false 并且此变量不应在此处注入作用域:

      $builder->{$scope}($value);
      

      相反,应该是这样的:

      if ($value == true) {
          $builder->{$scope}();
      }
      

      【讨论】:

      • 我在 github 上打开了一个关于这个 bug 的问题。感谢您的回答!
      • 经过 spawnia 的回复,我想出了正确的使用方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-18
      • 2012-01-25
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      相关资源
      最近更新 更多