บทช่วยสอน Schema
บทช่วยสอน Schemaบทเรียนที่ 4: การทำซ้ำบล็อกโพสต์หลายรายการพร้อมกัน

บทเรียนที่ 4: การทำซ้ำบล็อกโพสต์หลายรายการพร้อมกัน

เราสามารถขยายบทเรียนก่อนหน้านี้เพื่อทำซ้ำโพสต์หลายรายการด้วยคำขอ GraphQL เพียงคำขอเดียวได้

GraphQL query เพื่อทำซ้ำโพสต์หลายรายการพร้อมกัน

เพื่อให้ GraphQL query นี้ทำงานได้ การกำหนดค่าสคีมา ที่ใช้กับเอนด์พอยต์จำเป็นต้องเปิดใช้งาน Nested Mutations

GraphQL query นี้จะทำซ้ำโพสต์ที่ดึงมาผ่านตัวแปร $limit และ $offset ที่กำหนดไว้:

query InitializeDynamicVariables
  @configureWarningsOnExportingDuplicateVariable(enabled: false)
{
  postInputs: _echo(value: [])
    @export(as: "postInputs")
    @remove
}
 
query GetPostsAndExportData($limit: Int! = 5, $offset: Int! = 0)
  @depends(on: "InitializeDynamicVariables")
{
  postsToDuplicate: posts(
    pagination: {
      limit : $limit
      offset: $offset
    }
    sort: {
      by: ID,
      order: ASC
    }
  ) {
    # Fields not to be duplicated
    id
    slug
    date
    status
 
    # Fields to be duplicated
    author {
      id
    }
    categories {
      id
    }
    rawContent
    excerpt
    featuredImage {
      id
    }
    tags {
      id
    }
    title
 
    # Already create (and export) the inputs for the mutation
    postInputs: _echo(value: {
      status: draft,
      authorBy: {
        id: $__author
      },
      categoriesBy: {
        ids: $__categories
      },
      contentAs: {
        html: $__rawContent
      },
      excerpt: $__excerpt
      featuredImageBy: {
        id: $__featuredImage
      },
      tagsBy: {
        ids: $__tags
      },
      title: $__title
    })
      @export(as: "postInputs", type: LIST)
      @remove
  }
}
 
mutation DuplicatePosts
  @depends(on: "GetPostsAndExportData")
{
  createPosts(inputs: $postInputs) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      # Fields not to be duplicated
      id
      slug
      date
      status
 
      # Fields to be duplicated
      author {
        id
      }
      categories {
        id
      }
      rawContent
      excerpt
      featuredImage {
        id
      }
      tags {
        id
      }
      title
    }
  }
}

ทีละขั้นตอน: การสร้าง GraphQL query

ด้านล่างนี้คือการวิเคราะห์โดยละเอียดว่า query นี้ทำงานอย่างไร

การขยายบทเรียน "การทำซ้ำบล็อกโพสต์"

บทเรียนก่อนหน้านี้ใช้กลยุทธ์ต่อไปนี้ (กับ GraphQL query ของแนวทางที่สอง):

  1. เอ็กซ์พอร์ต ID ของรีซอร์สจากฟิลด์ (รวมถึงฟิลด์เชื่อมต่อ):
query GetPostAndExportData {
  post {
    author @export(as: "authorID") {
      id
    }
    categories @export(as: "categoryIDs") {
      id
    }
    rawContent @export(as: "rawContent")
    rawExcerpt @export(as: "excerpt")
    featuredImage @export(as: "featuredImageID") {
      id 
    }
    tags @export(as: "tagIDs") {
      id
    }
    rawTitle @export(as: "title")    
  }
}
  1. สร้างอ็อบเจกต์ input สำหรับ createPost(input:) จากตัวแปรไดนามิกเหล่านั้น:
mutation DuplicatePost
  @depends(on: "GetPostAndExportData")
{
  createPost(input: {
    status: draft,
    authorBy: {
      id: $authorID
    },
    categoriesBy: {
      ids: $categoryIDs
    },
    contentAs: {
      html: $rawContent
    },
    excerpt: $excerpt
    featuredImageBy: {
      id: $featuredImageID
    },
    tagsBy: {
      ids: $tagIDs
    },
    title: $title
  }) {
    # ...
  }
}

ด้วยส่วนขยาย Field to Input เราสามารถสร้างอ็อบเจกต์ input ในออเปอเรชันแรกได้เลย และเอ็กซ์พอร์ตข้อมูลโพสต์ที่จำเป็นทั้งหมดภายใต้ตัวแปรไดนามิกเพียงตัวเดียว:

query GetPostAndExportData {
  post {
    author {
      id
    }
    categories {
      id
    }
    rawContent
    excerpt
    featuredImage {
      id
    }
    tags {
      id
    }
    title
 
    postInputs: _echo(value: {
      status: draft,
      authorBy: {
        id: $__author
      },
      categoriesBy: {
        ids: $__categories
      },
      contentAs: {
        html: $__rawContent
      },
      excerpt: $__excerpt
      featuredImageBy: {
        id: $__featuredImage
      },
      tagsBy: {
        ids: $__tags
      },
      title: $__title
    })
      @export(as: "postInputs")
  }
}

จากนั้น ในมิวเทชันถัดไป createPost(input:) จะรับตัวแปรไดนามิก $postInputs โดยตรง:

mutation DuplicatePost
  @depends(on: "GetPostAndExportData")
{
  createPost(input: $postInputs) {
    # ...
  }
}

การดึงโพสต์หลายรายการ

เราต้องแปลง query เพื่อดึงโพสต์หลายรายการที่จะทำซ้ำ:

  • Query โพสต์ผ่าน posts(pagination: { limit : $limit, offset: $offset}) { ... }
  • เอ็กซ์พอร์ต postInputs เป็นลิสต์ (กล่าวคืออาร์เรย์ที่บรรจุ input ทั้งหมดของโพสต์ที่ query มา)
query GetPostsAndExportData($limit: Int! = 5, $offset: Int! = 0)
  @depends(on: "InitializeDynamicVariables")
{
  postsToDuplicate: posts(
    pagination: {
      limit : $limit
      offset: $offset
    }
    sort: {
      by: ID,
      order: ASC
    }
  ) {
    # ...
 
    postInputs: _echo(value: {
      # ...
    })
      @export(
        as: "postInputs",
        type: LIST
      )
  }
}

การสร้างโพสต์หลายรายการด้วย GraphQL query เพียงคำขอเดียว

ตอนนี้ตัวแปรไดนามิก $postInputs บรรจุอาร์เรย์ที่มีข้อมูล input ทั้งหมดของแต่ละโพสต์ที่จะทำซ้ำ:

[
  {
    "status": "draft",
    "authorBy": {
      "id": "2"
    },
    "categoryIDs": [
      1
    ],
    "contentAs": {
      "html": "<!-- wp:paragraph -->\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!</p>\n<!-- /wp:paragraph -->"
    },
    "excerpt": "Welcome to WordPress. This is your first post. Edit or delete it, then start writing!",
    "featuredImageBy": {
      "id": null
    },
    "tagsBy": {
      "ids": []
    },
    "title": "Hello world!"
  },
  {
    "status": "draft",
    "authorBy": {
      "id": "3"
    },
    "categoryIDs": [
      3
    ],
    "contentAs": {
      "html": "<!-- wp:paragraph -->\n<p>This is a paragraph block. Professionally productize highly efficient results with world-class core competencies. Objectively matrix leveraged architectures vis-a-vis error-free applications. Completely maximize customized portals via fully researched metrics. Enthusiastically generate premier action items through web-enabled e-markets. Efficiently parallel task holistic intellectual capital and client-centric markets.<br><br></p>\n<!-- /wp:paragraph -->\n\n<!-- wp:heading -->\n<h2>Image Block (Standard)</h2>\n<!-- /wp:heading -->\n\n<!-- wp:image {\"id\":1755} -->\n<figure class=\"wp-block-image\"><img src=\"https://d.pr/i/8pTmgY+\" alt=\"\" class=\"wp-image-1755\"/></figure>\n<!-- /wp:image -->"
    },
    "excerpt": "This is a paragraph block. Professionally productize highly efficient results with world-class core competencies. Objectively matrix leveraged architectures vis-a-vis error-free applications. Completely maximize customized portals via fully researched metrics. Enthusiastically generate premier action items through web-enabled e-markets. Efficiently parallel task holistic intellectual capital and client-centric markets. Image Block (Standard)",
    "featuredImageBy": {
      "id": 361
    },
    "tagsBy": {
      "ids": [
        11,
        10
      ]
    },
    "title": "Released v0.6, check it out"
  }
]

สุดท้าย เราเรียกบัลก์มิวเทชัน createPosts เพื่อสร้างโพสต์ทั้งหมดโดยส่งข้อมูลของ input ที่เอ็กซ์พอร์ตไว้:

mutation DuplicatePosts
  @depends(on: "GetPostsAndExportData")
{
  createPosts(inputs: $postInputs) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      # Fields not to be duplicated
      id
      slug
      date
      status
 
      # Fields to be duplicated
      author {
        id
      }
      categories {
        id
      }
      rawContent
      excerpt
      featuredImage {
        id
      }
      tags {
        id
      }
      title
    }
  }
}

สุดท้าย เราเรียกบัลก์มิวเทชัน createPosts เพื่อสร้างโพสต์ทั้งหมดโดยส่ง input ทั้งหมด:

mutation DuplicatePosts
  @depends(on: "GetPostsAndExportData")
{
  createPosts(inputs: $postInputs) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      # Fields not to be duplicated
      id
      slug
      date
      status
 
      # Fields to be duplicated
      author {
        id
      }
      categories {
        id
      }
      rawContent
      excerpt
      featuredImage {
        id
      }
      tags {
        id
      }
      title
    }
  }
}

การลบข้อมูลที่ไม่จำเป็น

ขั้นตอนสุดท้ายคือการลบฟิลด์ที่เป็นส่วนเสริมทั้งหมด (ซึ่งเราไม่จำเป็นต้องแสดงผลลัพธ์ในเรสปอนส์) ด้วย @remove

GraphQL query ที่รวมเข้าด้วยกันคือ:

query InitializeDynamicVariables
  @configureWarningsOnExportingDuplicateVariable(enabled: false)
{
  postInputs: _echo(value: [])
    @export(as: "postInputs")
    @remove
}
 
query GetPostsAndExportData($limit: Int! = 5, $offset: Int! = 0)
  @depends(on: "InitializeDynamicVariables")
{
  postsToDuplicate: posts(
    pagination: {
      limit : $limit
      offset: $offset
    }
    sort: {
      by: ID,
      order: ASC
    }
  ) {
    # Fields not to be duplicated
    id
    slug
    date
    status
 
    # Fields to be duplicated
    author {
      id
    }
    categories {
      id
    }
    rawContent
    excerpt
    featuredImage {
      id
    }
    tags {
      id
    }
    title
 
    # Already create (and export) the inputs for the mutation
    postInputs: _echo(value: {
      status: draft,
      authorBy: {
        id: $__author
      },
      categoriesBy: {
        ids: $__categories
      },
      contentAs: {
        html: $__rawContent
      },
      excerpt: $__excerpt
      featuredImageBy: {
        id: $__featuredImage
      },
      tagsBy: {
        ids: $__tags
      },
      title: $__title
    })
      @export(as: "postInputs", type: LIST)
      @remove
  }
}
 
mutation DuplicatePosts
  @depends(on: "GetPostsAndExportData")
{
  createPosts(inputs: $postInputs) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      # Fields not to be duplicated
      id
      slug
      date
      status
 
      # Fields to be duplicated
      author {
        id
      }
      categories {
        id
      }
      rawContent
      excerpt
      featuredImage {
        id
      }
      tags {
        id
      }
      title
    }
  }
}