add_action('graphql_register_types', function() {
register_graphql_field('Campaign', 'campaignDuration', [
'type' => 'String',
'description' => __('Durata campaniei calculata direct in backend', 'text-domain'),
'resolve' => function($post) {
$start = get_field('data_start', $post->ID);
$end = get_field('data_sfarsit', $post->ID);
if (!$start || !$end) {
return null;
}
return sprintf('Campanie activa intre %s si %s', $start, $end);
}
]);
});Am lucrat recent la un proiect headless pe WooCommerce pentru un magazin de fashion cu vreo 12.000 de produse active. Pe lângă catalogul clasic de produse, clientul voia pagini de campanii editoriale foarte customizate. Am rezolvat rapid structura în backend cu Custom Post Types (CPT) și Advanced Custom Fields (ACF). Totul frumos în wp-admin, dar când a trebuit să trimitem datele către un frontend în Next.js, ne-am lovit de clasica problemă: cum expunem datele curat, fără să descărcăm un JSON de 2MB la fiecare request.
Implicit, WordPress e extrem de darnic cu datele. Dacă nu ești atent, trimiți zeci de câmpuri inutile de care frontend-ul nu are nevoie.
REST API: Capcana default-ului
Dacă mergi pe REST API-ul nativ din WordPress, e simplu la prima vedere. Pui 'show_in_rest' => true la înregistrarea CPT-ului, bifezi în ACF „Show in REST API” și gata, ai ruta activă. Dar ai văzut vreodată cum arată răspunsul ăla implicit?
Primești tone de metadate, link-uri de rute interne (hal+json), statusuri de comentarii și layout-uri care nu-și au locul într-o aplicație decoupled. La proiectul de care vă ziceam, am redus payload-ul API-ului cu aproape 60% doar eliminând rutele implicite și mapând strict ce aveam nevoie.
Trade-off-ul aici e destul de clar: REST e super ușor de debuguit direct în browser, dar devine incredibil de greoi dacă ai relații complexe între postări (de exemplu, o campanie care are o listă de produse recomandate).
WPGraphQL: Calea curată pentru headless
Pentru headless, WPGraphQL combinat cu extensia WPGraphQL for ACF este, după părerea mea, soluția corectă. În loc să faci 3 request-uri HTTP separate pentru a lua campania, autorul și produsele asociate, iei totul într-un singur query.
După ce instalezi plugin-urile, în ecranul de editare ACF îți va apărea o secțiune nouă numită „GraphQL”. Aici trebuie să îi dai grupului de câmpuri un nume de query (de exemplu campaignFields).
Aici apare însă un alt trade-off major de performanță. Dacă ai relații de tip „Post Object” sau „Relationship” în ACF, interogările pot deveni extrem de lente (clasica problemă N+1). Pe proiectul nostru, un query GraphQL neoptimizat dura inițial 1.4 secunde. După ce am implementat un plugin de cache dedicat pentru GraphQL și am mapat corect tipurile de date, timpul de răspuns a scăzut sub 150ms.
Maparea manuală a câmpurilor custom
Uneori, pluginul automat de ACF pentru GraphQL nu expune datele exact cum vrei tu. De exemplu, dacă vrei să formatezi o dată direct din PHP sau să trimiți o imagine gata redimensionată pentru un anumit layout de mobil, cel mai bine este să înregistrezi manual câmpul în schema GraphQL.
În codul de mai jos aveți un exemplu concret despre cum adăugăm un câmp calculat direct în schema GraphQL pentru un Custom Post Type numit campaign.
Voi ce folosiți pentru proiectele headless cu WordPress? Ați rămas pe REST API-ul nativ (cu filtre în PHP) sau ați trecut complet pe WPGraphQL?