Dinamik yapılandırmalı veri getirme
WordPress'te iç içe geçmiş veri düzeylerini, yani aynı türden alt öğeler içeren varlıkları getirebiliriz. Örneğin, bir menü, alt öğeleri olabilen öğeler içerebilir; bu alt öğeler de kendi içlerinde alt öğeler barındırabilir ve bu böyle birkaç düzey devam edebilir. Benzer şekilde, bir yorum, kendileri de yanıt içerebilecek yanıtlara sahip olabilir.
GraphQL'de menülerle nasıl çalışacağımıza bakalım. GraphQL'de menü verilerini getirmek, menü içindeki öğeleri tüm farklı düzeyler için sorgulamayı gerektirir. Örneğin, aşağıdaki queries'te menünün 3 düzeyi vardır ve tüm düzeylerdeki menü öğeleri için aynı alanları (id, label ve url) getirmek üzere MenuItemProps fragment'ını kullanırız:
query GetMenu {
menu(by: { id: 176 }) {
id
items {
...MenuItemProps
children {
...MenuItemProps
children {
...MenuItemProps
}
}
}
}
}
fragment MenuItemProps on MenuItem {
id
label
url
}Görüldüğü üzere, düzey sayısı GraphQL queries'ine yansımaktadır. Uygulamadaki menünün 3 düzeyi olduğundan, GraphQL queries'inin de 3 iç içe geçme düzeyi vardır.
Ancak WordPress'te menünün oluşturulması önceden belirlenmez; bunun yerine sitenin yöneticisi tarafından Menü ekranı aracılığıyla yapılandırılır (yani "block theme" kullanılmadığında) ve veritabanında saklanır:

Bu bir sorun oluşturur: kullanıcı arayüzü aracılığıyla menüye fazladan bir düzey eklendiğinde, GraphQL queries'ine de fazladan bir düzey eklememiz gerekir; aksi takdirde yeni düzey sitede görüntülenmez.
Bu sorunla başa çıkmanın 2 yolu vardır. Daha basit olanı, başlangıçta ihtiyaç duyulandan daha fazla düzey getiren GraphQL queries'i oluşturmaktır; böylece daha sonra düzey eklemeye devam etmek için alan kalır. Örneğin, uygulama 3 düzeye ihtiyaç duyuyorsa GraphQL queries'i yine de 6 (ya da 10 ya da 20) düzey için veri getirebilir; bu da limite ulaşana kadar menüyü genişletmemiz için yeterli alan sağlar:
query GetMenu {
menu(by: { id: 176 }) {
id
items {
...MenuItemProps
children {
...MenuItemProps
children {
...MenuItemProps
children {
...MenuItemProps
children {
...MenuItemProps
children {
...MenuItemProps
}
}
}
}
}
}
}
}
fragment MenuItemProps on MenuItem {
id
label
url
}İkinci çözüm, tüm düzey ve alt düzeyler dahil olmak üzere menünün tüm verilerini içeren yapılandırılmış bir JSONObject üretecek olan Menu.itemDataEntries alanını kullanmaktır:
query GetMenu {
menu(by: { id: 176 }) {
id
itemDataEntries
}
}Bu queries'e verilen yanıt şöyle görünür:
{
"data": {
"menu": {
"id": 176,
"itemDataEntries": [
{
"id": 735,
"objectID": "6",
"parentID": null,
"label": "About The Tests",
"url": "https://mywpsite.com/about/",
"children": [
{
"id": 1451,
"objectID": "1133",
"parentID": "735",
"label": "Page Image Alignment",
"url": "https://mywpsite.com/about/page-image-alignment/",
"children": []
},
{
"id": 1452,
"objectID": "1134",
"parentID": "735",
"label": "Page Markup And Formatting",
"url": "https://mywpsite.com/about/page-markup-and-formatting/",
"children": []
}
]
},
{
"id": 739,
"objectID": "174",
"parentID": null,
"label": "Level 1",
"url": "https://mywpsite.com/level-1/",
"children": [
{
"id": 740,
"objectID": "173",
"parentID": "739",
"label": "Level 2",
"url": "https://mywpsite.com/level-1/level-2/",
"children": [
{
"id": 741,
"objectID": "172",
"parentID": "740",
"label": "Level 3",
"url": "https://mywpsite.com/level-1/level-2/level-3/",
"children": []
},
{
"id": 1453,
"objectID": "747",
"parentID": "740",
"label": "Level 3a",
"url": "https://mywpsite.com/level-1/level-2/level-3a/",
"children": []
},
{
"id": 1454,
"objectID": "748",
"parentID": "740",
"label": "Level 3b",
"url": "https://mywpsite.com/level-1/level-2/level-3b/",
"children": []
}
]
}
]
},
{
"id": 742,
"objectID": "146",
"parentID": null,
"label": "Lorem Ipsum",
"url": "https://mywpsite.com/lorem-ipsum/",
"children": []
}
]
}
}
}Bu yöntemin avantajı, alınan verilerin tamamen kullanıcı arayüzü tarafından yönlendirilmesi ve veritabanında depolananı olduğu gibi yansıtmasıdır; dolayısıyla menüye ister 2 ister 20 düzey eklensin, uygulamanın hiçbir zaman güncellenmesi gerekmez.
Ancak bu yöntemin açık bir dezavantajı vardır: GraphQL'in güçlü yazımını kaybederiz. url alanını URL, label alanını String, objectID alanını ID gibi güçlü türlere sahip bir menü öğesi almak yerine, Apollo client veya Relay gibi GraphQL araçları ve istemcileri tarafından anlaşılmayacak düz bir nesne elde ederiz. Bu nedenle GraphQL'in avantajlarından tam anlamıyla yararlanamayız.
WordPress ayar verilerini getirme
Bir diğer sorun, kullanıcı arayüzü tarafından yönlendirilen ve veritabanında saklanan varlıkları getirmemiz gerektiğinde ortaya çıkar. Bu durum WordPress'teki ayarlarda söz konusudur; burada seçenek adları tema ve eklentiler tarafından dinamik olarak oluşturulduğundan GraphQL sunucusu tarafından önceden bilinmez. Meta değerler de tema ve eklentiler tarafından tanımlanabilir; bu nedenle varsayılan olarak GraphQL şemasına eşlenmez.
Bu nedenle Gato GraphQL tarafından üretilen şema, seçenek adlarını ve türlerini sabit olarak kodlamaz; bunun yerine bunlara, seçeneğin adını alan ve olası yerleşik türlerden herhangi birinin değerini (AnyBuiltInScalar ile temsil edilen) döndüren bir optionValue alanı (ayrıca optionValues ve optionObjectValue) aracılığıyla erişilir:
type Root {
optionValue(name: String!): AnyBuiltInScalar
}Tüm seçeneklerin API aracılığıyla açığa çıkarılması amaçlanmadığından, sitenin yöneticisinin bunları tam adlarıyla ya da bir regex ile eklenti ayarlarındaki izin listesine açıkça eklemesi gerekir:

Artık queries, izin listesindeki seçenekleri getirebilir:
{
siteURL: optionValue(name: "siteurl")
siteName: optionValue(name: "blogname")
siteDescription: optionValue(name: "blogdescription")
}Uygulama için ihtiyaç duyulan fazladan bir seçenek varsa, Ayarlar sayfasındaki izin listesine karşılık gelen bir giriş eklenerek bu seçenek API'ye hemen kullanılabilir hale getirilebilir.