Query Functions
Query Functionsการวนซ้ำและการจัดการค่าของฟิลด์

การวนซ้ำและการจัดการค่าของฟิลด์

Included in the “Power Extensions” bundle

การเพิ่มเมตาไดเรกทีฟให้กับ GraphQL schema เพื่อวนซ้ำและจัดการองค์ประกอบค่าของฟิลด์ประเภท array และ object:

  1. @underArrayItem
  2. @underJSONObjectProperty
  3. @underEachArrayItem
  4. @underEachJSONObjectProperty
  5. @objectClone

@underArrayItem

@underArrayItem ทำให้ไดเรกทีฟที่ซ้อนอยู่ถูกนำไปใช้กับองค์ประกอบที่ระบุภายใน array

ในเควรีด้านล่าง มีเพียงองค์ประกอบแรกใน array ของชื่อหมวดหมู่เท่านั้นที่ถูกแปลงเป็นตัวพิมพ์ใหญ่:

query {
  posts {
    categoryNames
      @underArrayItem(index: 0)
        @strUpperCase
  }
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "posts": {
      "categoryNames": [
        "NEWS",
        "sports"
      ]
    }
  }
}

@underJSONObjectProperty

@underJSONObjectProperty ทำให้ไดเรกทีฟที่ซ้อนอยู่ได้รับเอนทรีจาก JSON object ที่ถูกเควรี

ไดเรกทีฟนี้มีประโยชน์อย่างยิ่งในการดึงและจัดการข้อมูลที่ต้องการหลังจากเควรี API ภายนอก ซึ่งมักจะมีประเภทเป็น JSONObject แบบทั่วไป (เช่นเมื่อใช้ฟังก์ชันฟิลด์ _sendJSONObjectItemHTTPRequest จากเอ็กซ์เทนชัน HTTP Client)

ในเควรีด้านล่าง เราได้รับ JSON object จาก WP REST API และเราใช้ @underJSONObjectProperty เพื่อจัดการพร็อพเพอร์ตี type ของการตอบกลับ โดยแปลงเป็นตัวพิมพ์ใหญ่:

query {
  postData: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://newapi.getpop.org/wp-json/wp/v2/posts/1/?_fields=id,type,title,date"
  })
    @underJSONObjectProperty(by: { key: "type" })
      @strUpperCase
}

ซึ่งจะให้ผลลัพธ์ดังนี้:

{
  "data": {
    "postData": {
      "id": 1,
      "date": "2019-08-02T07:53:57",
      "type": "POST",
      "title": {
        "rendered": "Hello world!"
      }
    }
  }
}

นอกจากการรับ "key" เพื่อชี้ไปยังพร็อพเพอร์ตีที่อยู่ในระดับแรกของ JSON object แล้ว ไดเรกทีฟนี้ยังสามารถรับ "path" เพื่อนำทางภายในโครงสร้างของ object โดยใช้ . เป็นตัวคั่นระหว่างระดับได้อีกด้วย

ในเควรีด้านล่าง เอนด์พอยต์ WP REST API สำหรับโพสต์ให้พร็อพเพอร์ตี "title.rendered" มา เราสามารถนำทางไปยังซับอิลิเมนต์นั้นจริง ๆ และแปลงให้เป็นแบบ title case ได้:

query {
  postData: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://newapi.getpop.org/wp-json/wp/v2/posts/1/?_fields=id,type,title,date"
  })
    @underJSONObjectProperty(by: { path: "title.rendered" })
      @strTitleCase
}

ซึ่งจะให้ผลลัพธ์ดังนี้:

{
  "data": {
    "postData": {
      "id": 1,
      "date": "2019-08-02T07:53:57",
      "type": "post",
      "title": {
        "rendered": "HELLO WORLD!"
      }
    }
  }
}

@underEachArrayItem

@underEachArrayItem วนซ้ำองค์ประกอบ array จากฟิลด์บางตัวในเอนทิตีที่ถูกเควรี และเรียกใช้ไดเรกทีฟที่ซ้อนอยู่กับแต่ละองค์ประกอบ

ตัวอย่างเช่น ฟิลด์ Post.categoryNames มีประเภทเป็น [String] เมื่อใช้ @underEachArrayItem เราสามารถวนซ้ำชื่อหมวดหมู่และนำไดเรกทีฟ @strTranslate ไปใช้กับชื่อเหล่านั้นได้

ในเควรีนี้ หมวดหมู่ของโพสต์ถูกแปลจากภาษาอังกฤษเป็นภาษาฝรั่งเศส:

query {
  posts {
    id
    title
    categoryNames
      @underEachArrayItem
        @strTranslate(
          from: "en",
          to: "fr"
        )
  }
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "posts": [
      {
        "id": 662,
        "title": "Explaining the privacy policy",
        "categoryNames": [
          "Non classé"
        ]
      },
      {
        "id": 28,
        "title": "HTTP caching improves performance",
        "categoryNames": [
          "Avancé"
        ]
      },
      {
        "id": 25,
        "title": "Public or Private API mode, for extra security",
        "categoryNames": [
          "Ressource",
          "Blog",
          "Avancé"
        ]
      }
    ]
  }
}

@underEachArrayItem สามารถส่งทั้งดัชนีและค่าขององค์ประกอบที่กำลังวนซ้ำเป็นตัวแปรไดนามิกไปยังไดเรกทีฟที่ซ้อนอยู่ ผ่านอาร์กิวเมนต์ไดเรกทีฟ passIndexOnwardsAs และ passValueOnwardsAs

เควรีนี้แสดงตัวอย่างการใช้ตัวแปรไดนามิก $index และ $value:

{
  _echo(value: ["first", "second", "third"])
    @underEachArrayItem(
      passIndexOnwardsAs: "index"
      passValueOnwardsAs: "value"
    )
      @applyField(
        name: "_echo"
        arguments: {
          value: {
            index: $index,
            value: $value
          }
        },
        setResultInResponse: true
      )
}

ผลลัพธ์คือ:

{
  "data": {
    "_echo": [
      {
        "index": 0,
        "value": "first"
      },
      {
        "index": 1,
        "value": "second"
      },
      {
        "index": 2,
        "value": "third"
      }
    ]
  }
}

@underEachArrayItem ยังสามารถจำกัดตำแหน่งของ array ที่จะวนซ้ำได้ ผ่านพารามิเตอร์ filter->by ซึ่งสามารถรับเอนทรี include หรือ exclude ก็ได้

เควรีนี้:

{
  including: _echo([
    "first",
    "second",
    "third"
  ])
    @underEachArrayItem(
      filter: {
        by: {
          include: [0, 2]
        }
      }
    )
      @strUpperCase
 
  excluding: _echo([
    "first",
    "second",
    "third"
  ])
    @underEachArrayItem(
      filter: {
        by: {
          exclude: [0, 2]
        }
      }
    )
      @strUpperCase
}

...produces:

{
  "data": {
    "including": [
      "FIRST",
      "second",
      "THIRD"
    ],
    "excluding": [
      "first",
      "SECOND",
      "third"
    ]
  }
}

@underEachJSONObjectProperty

@underEachJSONObjectProperty คล้ายกับ @underEachArrayItem แต่ทำงานกับองค์ประกอบ JSONObject

ในเควรีนี้ เราวนซ้ำทุกเอนทรีใน JSON object และแทนที่เอนทรี null ใด ๆ ด้วยสตริงว่าง:

{
  _echo(
    value: {
      first: "hello",
      second: "world",
      third: null
    }
  )
    @underEachJSONObjectProperty
      @default(value: "")
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "_echo": {
      "first": "hello",
      "second": "world",
      "third": ""
    }
  }
}

@underEachJSONObjectProperty สามารถส่งคีย์และค่าที่กำลังวนซ้ำเป็นตัวแปรไดนามิกไปยังไดเรกทีฟที่ซ้อนอยู่ ผ่านอาร์กิวเมนต์ไดเรกทีฟ passKeyOnwardsAs และ passValueOnwardsAs

เควรีนี้แสดงตัวอย่างการใช้ตัวแปรไดนามิก $key และ $value:

{
  _echo(value: {
    uno: "first",
    dos: "second",
    tres: "third"
  })
    @underEachJSONObjectProperty(
      passKeyOnwardsAs: "key"
      passValueOnwardsAs: "value"
    )
      @applyField(
        name: "_echo"
        arguments: {
          value: {
            key: $key,
            value: $value
          }
        },
        setResultInResponse: true
      )
}

ผลลัพธ์คือ:

{
  "data": {
    "_echo": {
      "uno": {
        "key": "uno",
        "value": "first"
      },
      "dos": {
        "key": "dos",
        "value": "second"
      },
      "tres": {
        "key": "tres",
        "value": "third"
      }
    }
  }
}

@underEachJSONObjectProperty ยังสามารถจำกัดคีย์จาก JSON object ที่จะวนซ้ำได้ ผ่านพารามิเตอร์ filter->by ซึ่งสามารถรับเอนทรี includeKeys หรือ excludeKeys ก็ได้

เควรีนี้:

{
  includingKeys: _echo(value: {
    uno: "first",
    dos: "second",
    tres: "third"
  })
    @underEachJSONObjectProperty(
      filter: {
        by: {
          includeKeys: ["uno", "tres"]
        }
      }
    )
      @strUpperCase
 
  excludingKeys: _echo(value: {
    uno: "first",
    dos: "second",
    tres: "third"
  })
    @underEachJSONObjectProperty(
      filter: {
        by: {
          excludeKeys: ["uno", "tres"]
        }
      }
    )
      @strUpperCase
}

...produces:

{
  "data": {
    "includingKeys": {
      "uno": "FIRST",
      "dos": "second",
      "tres": "THIRD"
    },
    "excludingKeys": {
      "uno": "first",
      "dos": "SECOND",
      "tres": "third"
    }
  }
}

@objectClone

JSON object อาจถูกเข้าถึงโดยการอ้างอิงในฟิลด์รีโซลเวอร์ (ไม่ใช่โดยการคัดลอก/ทำสำเนา object) ในกรณีนั้น เมื่อ JSON object ถูกแก้ไข การแก้ไขนี้จะปรากฏให้เห็นในทุกฟิลด์ที่ดึง JSON object นี้

นี่คือกรณีของฟิลด์ Block.attributes:

{
  posts {
    blocks(filterBy: { include: "core/heading" } ) {
      attributes
    }
  }
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "posts": [
      {
        "blocks": [
          {
            "attributes": {
              "content": "Image Block (Full width)",
              "level": 2
            }
          },
          {
            "attributes": {
              "content": "Gallery Block",
              "level": 2
            }
          }
        ]
      }
    ]
  }
}

ในเควรีด้านล่าง ขณะที่ originalAttributes เพียงแค่ดึงแอตทริบิวต์มา transformedAttributes จะแปลพร็อพเพอร์ตี content เป็นภาษาฝรั่งเศสด้วย:

{
  posts {
    blocks(filterBy: { include: "core/heading" } ) {
      originalAttributes: attributes
      transformedAttributes: attributes
        @underJSONObjectProperty(by: { key: "content" })
          @strTranslate(to: "fr")
    }
  }
}

อย่างไรก็ตาม เนื่องจากเอนทิตี Block ที่ถูกเควรีอ้างอิงไปยัง JSON object เดียวกันทั้งใน originalAttributes และ transformedAttributes การแปลงที่ทำโดยฟิลด์หลังจึงส่งผลต่อฟิลด์แรกด้วย (โดยไม่ขึ้นกับลำดับที่ปรากฏในเควรี)

ผลที่ได้คือ ทั้งสองฟิลด์ถูกแปลเป็นภาษาฝรั่งเศส:

{
  "data": {
    "posts": [
      {
        "blocks": [
          {
            "originalAttributes": {
              "content": "Bloc d'image (pleine largeur)",
              "level": 2
            },
            "transformedAttributes": {
              "content": "Bloc d'image (pleine largeur)",
              "level": 2
            }
          },
          {
            "originalAttributes": {
              "content": "Bloc Galerie",
              "level": 2
            },
            "transformedAttributes": {
              "content": "Bloc Galerie",
              "level": 2
            }
          }
        ]
      }
    ]
  }
}

เราสามารถหลีกเลี่ยงปัญหานี้ได้โดยการเพิ่มไดเรกทีฟ @objectClone ลงในฟิลด์ transformedAttributes เพื่อให้การแก้ไขถูกดำเนินการบน JSON object ที่ถูกโคลน:

{
  posts {
    blocks(filterBy: { include: "core/heading" } ) {
      originalAttributes: attributes
      transformedAttributes: attributes
        @objectClone
        @underJSONObjectProperty(by: { key: "content" })
          @strTranslate(to: "fr")
    }
  }
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "posts": [
      {
        "blocks": [
          {
            "originalAttributes": {
              "content": "Image Block (Full width)",
              "level": 2
            },
            "transformedAttributes": {
              "content": "Bloc d'image (pleine largeur)",
              "level": 2
            }
          },
          {
            "originalAttributes": {
              "content": "Gallery Block",
              "level": 2
            },
            "transformedAttributes": {
              "content": "Bloc Galerie",
              "level": 2
            }
          }
        ]
      }
    ]
  }
}

ตัวอย่างเพิ่มเติม

ในเควรีนี้ @underEachArrayItem ห่อหุ้ม @underJSONObjectProperty ซึ่งห่อหุ้ม @strUpperCase อีกที โดยแปลงพร็อพเพอร์ตี "title.rendered" เป็นตัวพิมพ์ใหญ่ สำหรับโพสต์หลายรายการที่ได้รับผ่าน WP REST API:

query {
  postListData: _sendJSONObjectCollectionHTTPRequest(
    url: "https://newapi.getpop.org/wp-json/wp/v2/posts/?per_page=3&_fields=id,type,title,date"
  )
    @underEachArrayItem
      @underJSONObjectProperty(by: { path: "title.rendered" })
        @strUpperCase
}

...ซึ่งให้ผลลัพธ์:

{
  "data": {
    "postListData": [
      {
        "id": 1692,
        "date": "2022-04-26T10:10:08",
        "type": "post",
        "title": {
          "rendered": "MY BLOGROLL"
        }
      },
      {
        "id": 1657,
        "date": "2020-12-21T08:24:18",
        "type": "post",
        "title": {
          "rendered": "A TALE OF TWO CITIES – TEASER"
        }
      },
      {
        "id": 1499,
        "date": "2019-08-08T02:49:36",
        "type": "post",
        "title": {
          "rendered": "COPE WITH WORDPRESS: POST DEMO CONTAINING PLENTY OF BLOCKS"
        }
      }
    ]
  }
}