การเขียนโค้ดด้วย API
การเขียนโค้ดด้วย APIการเสริม WP-CLI

การเสริม WP-CLI

WP-CLI เป็นเครื่องมือบรรทัดคำสั่งสำหรับโต้ตอบกับ WordPress ที่ช่วยให้เราทำงานซ้ำๆ ได้โดยอัตโนมัติ รองรับการติดตั้งไซต์ใหม่ สร้างหรืออัปเดตโพสต์ เปิดใช้งานปลั๊กอิน แก้ไขค่าตัวเลือก และอื่นๆ อีกมากมาย

คำสั่ง WP-CLI สามารถซ้อนกันได้:

  1. รันคำสั่ง WP-CLI ที่คืนค่า ID ของทรัพยากรบางอย่าง
  2. นำ ID นั้นไปใส่ในคำสั่ง WP-CLI อีกคำสั่งหนึ่ง เพื่อดำเนินการกับทรัพยากรนั้น

ตัวอย่างเช่น สคริปต์นี้ค้นหา ID ของโพสต์ที่มี slug ที่กำหนด แล้วอัปเดต meta ของมัน:

wp post meta set $(wp post list --name="hello-world" --format=ids) _wp_page_template about.php

สคริปต์นี้สร้างรายการเมนูซ้ำๆ และกำหนด ID ของมันเป็น parent ของรายการเมนูใหม่อีกรายการหนึ่ง เพื่อกำหนดโครงสร้างลำดับชั้น ("Most ancestor menu item" > "Parent menu item" > "Child menu item"):

wp menu item add-custom bottom-menu "Child menu item" https://bbc.com --parent-id=$(wp menu item add-post bottom-menu 1 --title="Parent menu item" --parent-id=$(wp menu item add-post bottom-menu 1 --title="Most ancestor menu item" --porcelain) --porcelain)

Gato GraphQL สามารถเสริมความสามารถของ WordPress ในการค้นหาข้อมูล ดังนั้นเราจึงสามารถใช้ Gato GraphQL เพื่อค้นหาข้อมูลที่ต้องการ แล้วนำไปใส่ใน WP-CLI ได้เช่นกัน

queries ต่อไปนี้จะแสดงให้เห็นวิธีการทำเช่นนั้น

การรัน GraphQL query จากเทอร์มินัล

ลองใช้ GraphQL query เพื่อค้นหาผู้ใช้ที่มี locale ภาษาสเปน และรันคำสั่ง WP-CLI กับผู้ใช้นั้น

เราจำกัดผลลัพธ์ให้แสดงเพียง 1 คนก่อน (ผ่าน pagination: { limit: 1 }):

query {
  users(
    filter: {
      metaQuery: {
        key: "locale",
        compareBy: {
          stringValue: {
            value: "es_[A-Z]+"
            operator: REGEXP
          }
        }
      }
    },
    pagination: {
      limit: 1
    }
  ) {
    id
    name
    locale: metaValue(key: "locale")
  }
}

ในเทอร์มินัล เราสามารถใช้ curl (หรือเครื่องมือที่คล้ายกัน) เพื่อรัน query กับ GraphQL server โดยส่งข้อมูลดังต่อไปนี้:

  • ใช้เมธอด POST
  • Content type ที่รองรับคือ application/json
  • Body เป็น dictionary ที่มี entry "query" และ GraphQL query (และหากจำเป็น ก็มี "variables" และ "operationName" ด้วย)
  • query string ต้องจัดรูปแบบ: " ทั้งหมดต้อง escape เป็น \" และขึ้นบรรทัดใหม่ต้องแทนที่ด้วย \n
  • ชี้ไปที่ URL ของ endpoint จาก Gato GraphQL (ทั้ง single endpoint หรือ custom endpoint)
curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "query {\n  users(\n    filter: {\n      metaQuery: {\n        key: \"locale\",\n        compareBy: {\n          stringValue: {\n            value: \"es_[A-Z]+\"\n            operator: REGEXP\n          }\n        }\n      }\n    },\n    pagination: {\n      limit: 1\n    }\n  ) {\n    id\n    name\n    locale: metaValue(key: \"locale\")\n  }\n}"}' \
  https://mysite.com/graphql/

คำสั่งนี้จะแสดงผลตอบกลับในเทอร์มินัลโดยตรง:

{"data":{"users":[{"id":3,"name":"Subscriber Bennett","locale":"es_AR"}]}}

การดึง ID จาก GraphQL response

เช่นเดียวกับการใช้ --field=ID, --format=ids หรือ --porcelain ใน WP-CLI เราต้องหาวิธีดึงข้อมูลเฉพาะที่ต้องการจาก GraphQL response ในตัวอย่างนี้คือ user ID

เราเก็บ GraphQL response ไว้ในตัวแปรสภาพแวดล้อม (เช่น GRAPHQL_RESPONSE) และระบุ user ID ด้วย alias เฉพาะ (เช่น spanishLocaleUserID):

GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "query {\n  users(\n    filter: {\n      metaQuery: {\n        key: \"locale\",\n        compareBy: {\n          stringValue: {\n            value: \"es_[A-Z]+\"\n            operator: REGEXP\n          }\n        }\n      }\n    },\n    pagination: {\n      limit: 1\n    }\n  ) {\n    spanishLocaleUserID: id\n    name\n    locale: metaValue(key: \"locale\")\n  }\n}"}' \
  https://mysite.com/graphql/)

การรัน echo $GRAPHQL_RESPONSE ช่วยให้เราดู response ได้:

{"data":{"users":[{"spanishLocaleUserID":3,"name":"Subscriber Bennett","locale":"es_AR"}]}}

ต่อไป เรารัน grep ด้วย regex ที่ตรงกับรูปแบบ "spanishLocaleUserID":{ID} และดึง ID ไปเก็บในตัวแปรสภาพแวดล้อม SPANISH_LOCALE_USER_ID:

SPANISH_LOCALE_USER_ID=$(echo $GRAPHQL_RESPONSE \
  | grep -E -o '"spanishLocaleUserID\":(\d+)' \
  | cut -d':' -f2- | cut -d'"' -f2- | rev | cut -d'"' -f2- | rev)

ตอนนี้เราสามารถนำค่าของตัวแปรนี้ไปใส่ใน WP-CLI ได้แล้ว:

wp user update "$(echo $SPANISH_LOCALE_USER_ID)" --locale=fr_FR

ทำให้ GraphQL query อ่านง่ายขึ้น

เมื่อจัดรูปแบบ GraphQL query เพื่อนำไปใส่ใน curl มันจะอ่านได้ยากขึ้น

วิธีแก้ไขคือใช้คำสั่ง bash เช่น tr และ sed เพื่อทำการแปลง:

GRAPHQL_QUERY='
  query {
    users(
      filter: {
        metaQuery: {
          key: "locale",
          compareBy: {
            stringValue: {
              value: "es_[A-Z]+"
              operator: REGEXP
            }
          }
        }
      },
      pagination: {
        limit: 1
      }
    ) {
      spanishLocaleUserID: id
      name
      locale: metaValue(key: "locale")
    }
  }
'
GRAPHQL_BODY="{\"query\": \"$(echo $GRAPHQL_QUERY | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d $GRAPHQL_BODY \
  https://mysite.com/graphql/)

การเพิ่ม syntax highlighting ให้กับ GraphQL query

การพัฒนาต่อจากขั้นตอนก่อนหน้าคือการวาง GraphQL query ในไฟล์ .gql แยกต่างหาก ซึ่งสามารถแก้ไขด้วย editor (เช่น VSCode) และใช้ประโยชน์จาก syntax highlighting ได้:

# This query is stored in file "find-user-with-spanish-locale.gql"
query {
  users(
    filter: {
      metaQuery: {
        key: "locale",
        compareBy: {
          stringValue: {
            value: "es_[A-Z]+"
            operator: REGEXP
          }
        }
      }
    },
    pagination: {
      limit: 1
    }
  ) {
    spanishLocaleUserID: id
    name
    locale: metaValue(key: "locale")
  }
}

จากนั้น เราอ่านเนื้อหาของไฟล์นี้โดยใช้ cat:

GRAPHQL_QUERY=$(cat find-user-with-spanish-locale.gql)
GRAPHQL_BODY="{\"query\": \"$(echo $GRAPHQL_QUERY | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d $GRAPHQL_BODY \
  https://mysite.com/graphql/)