Käytännön opas CEL-lausekkeiden kirjoittamiseen CMS:ssä.
Käytännön opas CEL-lausekkeiden kirjoittamiseen CMS:ssä.
CEL (Common Expression Language) on CMS:ään sisäänrakennettu kevyt komentosarjakieli. Sen avulla voit kirjoittaa dynaamisia lausekkeita, jotka hakevat tietoja dokumenteista, lukevat URL-parametreja ja laskevat arvoja lennossa.
Kun CEL-komentosarja suoritetaan:
Your Script The Engine Result
| | |
v v v
documents.get("article", "intro") --> Fetches from database --> { headline: "Welcome", body: "..." }
.headline --> Extracts the field --> "Welcome"
Ajattele CEL:ää vain lukuun tarkoitettuna kyselykielenä. Se ei voi muokata tietokannan sisältöä – se ainoastaan lukee tietoja ja palauttaa lasketun tuloksen. Siksi sitä on turvallista käyttää kaikkialla CMS:ssä.
Jokaisella CEL-lausekkeella on käytettävissään kolme asiaa:
| Objekti | Mikä se on | Esimerkki |
|---|---|---|
documents | Hakee minkä tahansa dokumentin CMS:stä | documents.get("country", "us") |
meta | Nykyistä pyyntöä koskevat tiedot (kielialue, URL-parametrit) | meta.locale, meta.params.slug |
schema | Nykyisen dokumentin kenttämääritykset | schema.fields |
doc-objektillaKun kirjoitat CEL-lausekkeita dokumenttieditorissa, voit käyttää nykyisen dokumentin kenttäarvoja doc-objektin avulla. Tämä mahdollistaa lasketut kentät ja kenttien väliset viittaukset.
// Käytä nykyisen dokumentin price-kenttää
doc.price
// Laske kokonaissumma nykyisen dokumentin kentistä
doc.price * doc.quantity
// Ehdollinen tulos nykyisen dokumentin tilan perusteella
doc.status == "published" ? doc.title : "Draft: " + doc.title
doc-objekti sisältää kaikki muokattavan dokumentin kenttäarvot. Se on hyödyllinen esimerkiksi seuraavissa tapauksissa:
doc.price * doc.quantity)CEL:n tehokkain ominaisuus on dokumenttien hakeminen mistä tahansa CMS:n osasta.
Syntaksi: documents.get(schemaName, identifier)
Oletetaan, että CMS:ssä on article-dokumentti tunnisteella "welcome-post":
// Tallennettu CMS:ään muodossa: article / welcome-post
{
"headline": "Welcome to Our Platform",
"author": "Sarah Chen",
"body": "We're excited to announce...",
"tags": ["announcement", "news"]
}
Koko dokumentin hakeminen:
documents.get("article", "welcome-post")
Vain otsikon hakeminen:
documents.get("article", "welcome-post").headline
Tekijän hakeminen:
documents.get("article", "welcome-post").author
Kun sivullasi on dynaamisia reittejä, kuten /articles/[slug], voit käyttää meta.params-objektia URL-parametrin lukemiseen ja oikean dokumentin hakemiseen.
Jos käyttäjä avaa osoitteen /articles/welcome-post:
documents.get("article", meta.params.slug).headline
Näin rakennetaan dynaamisia sivuja: sama CEL-komentosarja toimii kaikille artikkeleille ja käyttää URL-osoitteessa olevaa slug-arvoa.
Syntaksi: documents.find(schemaName) tai documents.find(schemaName, filter)
// Hae kaikki maat
documents.find("country")
// Hae maat suodattimella
documents.find("country", { "where": { "code": "us" } })
CEL tukee käännetyn dokumenttisisällön hakemista kahdella tavalla: automaattisesti kielialueen perusteella tai hakemalla käännös eksplisiittisesti.
meta.locale-arvon avullaKun meta.locale on asetettu esimerkiksi reittiparametreista tai käyttäjän asetuksista, documents.get() yhdistää käännetyn sisällön automaattisesti:
// Jos meta.locale on "fr", palauttaa ranskankielisen käännöksen yhdistettynä perusdokumenttiin
documents.get("greeting", "welcome").headline
Toimintaperiaate:
meta.locale ei ole "en" tai "en-US", käännös haetaan translations-taulusta{ ...baseContent, ...translatedContent }Käännetyt kentät siis korvaavat peruskentät, kun taas kääntämättömät kentät käyttävät perusdokumentin arvoja.
documents.translated()-funktiollaJos haluat hakea tietyn käännöksen nykyisestä kielialueesta riippumatta:
Syntaksi: documents.translated(schemaName, identifier, locale)
// Hae aina espanjankielinen käännös
documents.translated("greeting", "welcome", "es").headline
// Hae käännös URL-parametrin perusteella
documents.translated("product", meta.params.id, meta.params.lang).description
// Vertaa käännöksiä
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title
Jos hero-block-lohkon tulee näyttää article-dokumentista haettu otsikko, käytä seuraavaa CEL-komentosarjaa:
documents.get("article", "homepage-hero").headline
Tulos: Sankarilohkossa näytetään "Build Faster, Ship Smarter".
Kun rakennat sivua osoitteeseen /countries/[code] ja haluat näyttää maan koko nimen:
documents.get("country", meta.params.code).name
Kun käyttäjä avaa /countries/us-osoitteen, meta.params.code on "us" ja tulos on "United States".
meta.locale == "ar-SA" ? "Welcome, everyone" : "Welcome"
Jos kielialue on "ar-SA", palautetaan "Welcome, everyone"; muussa tapauksessa palautetaan "Welcome".
documents.get("country", documents.get("article", "us-news").countryCode).name
Haku noutaa ensin artikkelin, lukee sen countryCode-kentän, hakee kyseisen maan ja palauttaa lopuksi maan nimen.
documents.get("article", meta.params.slug) != null
? documents.get("article", meta.params.slug).headline
: "Article Not Found"
Voit tarkistaa myös yksittäisen kentän olemassaolon:
documents.get("article", "intro").author != null
? documents.get("article", "intro").author
: "Unknown Author"
"featured" in documents.get("article", "welcome-post").tags
Palauttaa true, jos artikkelilla on "featured"-tunniste.
documents.get("article", "welcome-post").tags[0]
size(documents.get("article", "welcome-post").tags)
Ensimmäinen lauseke palauttaa ensimmäisen tunnisteen ja toinen tunnisteiden lukumäärän.
meta.paramsParametriset reitit ovat keskeisiä dynaamisten ja lokalisoitujen sivujen rakentamisessa. Kun määrittelet reittimallin, kuten /{lang}/landingPage, CMS poimii URL-osoitteen parametrit ja asettaa ne saataville meta.params-objektiin.
Reitit käyttävät dynaamisten osien määrittämiseen syntaksia :paramName tai {paramName}:
| Malli | Esimerkki-URL | Poimitut parametrit |
|---|---|---|
/:lang/landingPage | /ko/landingPage | { lang: "ko" } |
/{country}/{lang}/products | /us/en/products | { country: "us", lang: "en" } |
/articles/:slug | /articles/welcome-post | { slug: "welcome-post" } |
Reittiparametri voidaan sitoa dokumenttiskeemaan validointia varten:
{
"pattern": "/{lang}/landingPage",
"param_bindings": {
"lang": "language"
}
}
Tämä kertoo CMS:lle, että sen tulee poimia lang URL-osoitteesta, validoida se language-skeemaa vasten ja tarjota kelvollinen dokumentti ratkaistuissa parametreissa.
documents.get("greeting", meta.params.lang).headline
| URL | meta.params.lang | Tulos |
|---|---|---|
/ko/landingPage | "ko" | "Welcome" |
/en/landingPage | "en" | "Welcome" |
/ja/landingPage | "ja" | "Welcome" |
// Hae maan nimi
documents.get("country", meta.params.country).name
// Hae maahan perustuva tuoteluettelo
documents.find("product", { "where": { "country": meta.params.country } })
// Näytä maakohtainen tervehdys käyttäjän kielellä
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name
CMS validoi parametrit hierarkkisesti: ensin maan country-parametrin, sitten lang-parametrin ja tarvittaessa myös sen, että kieli sisältyy maan languages[]-taulukkoon.
meta.segments – URL-polun raakatiedotmeta.segments tarjoaa URL-polun taulukkona. Se on hyödyllinen, kun tarvitset sijaintiin perustuvan pääsyn ilman nimettyjä parametreja.
| URL-polku | meta.segments |
|---|---|
/articles/tech/ai-news | ["articles", "tech", "ai-news"] |
/ko/landingPage | ["ko", "landingPage"] |
/us/en/products/featured | ["us", "en", "products", "featured"] |
/ | [] |
meta.segments- ja meta.params-arvoja| Käyttötapaus | Paras lähestymistapa |
|---|---|
| Reittimallin nimetyt parametrit | meta.params.lang |
| Sijaintiin perustuva pääsy | meta.segments[0] |
| Polun syvyyden hakeminen | size(meta.segments) |
| Tarkistus, sisältääkö polku osan | "admin" in meta.segments |
// Hae ensimmäinen osa
meta.segments[0]
// Tarkista polun syvyys
size(meta.segments) > 2 ? "deep" : "shallow"
// Tarkista, ollaanko hallintaosiossa
"admin" in meta.segments ? "admin mode" : "public mode"
// Varavaihtoehto, jos parametria ei ole sidottu
has(meta.params.lang) ? meta.params.lang : meta.segments[0]
meta-objektin täydellinen viitemeta-objekti sisältää nykyiseen pyyntöön liittyvän asiayhteyden:
| Ominaisuus | Tyyppi | Kuvaus |
|---|---|---|
meta.locale | string | Nykyinen kielialuekoodi, esimerkiksi "en-US" tai "fi-FI" |
meta.params | Record<string, string> | URL-mallista poimitut reittiparametrit |
meta.segments | string[] | URL-polku osiin jaettuna |
meta.docId | string \| null | Nykyisen dokumentin UUID; uusilla dokumenteilla null |
meta.title | string | Nykyisen dokumentin otsikko |
meta.localeKielialuekoodi noudattaa BCP 47 -muotoa:
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"
meta.locale.split("-")[0] // Ei tuettu – käytä sen sijaan meta.params.lang-arvoa
meta.paramsReittiparametrit ovat aina merkkijonoja. CMS validoi ne sidottuja skeemoja vasten ennen arviointia:
meta.params.lang
meta.params.country
meta.params.slug
has(meta.params.category)
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)
meta.docId ja meta.titlemeta.docId != null ? "editing" : "creating new"
meta.docId != null ? documents.get("article", meta.docId).status : "draft"
"Editing: " + meta.title
meta.title.contains("Draft") ? "work in progress" : "published"
documents.ref() – ketjutetut hautKun skeema tunnetaan mutta tunniste on dynaaminen, voit käyttää selkeämpää syntaksia:
// Perinteinen tapa
documents.get("airports", meta.params.code).name
// ref()-menetelmällä
documents.ref("airports").get(meta.params.code).name
Molemmat tavat ovat vastaavia, mutta ref() tekee dynaamisen osan näkyvämmäksi.
documents.get("schema", "identifier")
documents.get("schema", "id").fieldName
documents.find("schema")
documents.find("schema", { "where": {...}})
documents.ref("schema").get(identifier)
documents.translated("schema", "id", "fr")
meta.locale
meta.params.xyz
meta.segments
meta.segments[0]
meta.docId
meta.title
doc.fieldName
== != < <= > >=
&& || !
condition ? valueIfTrue : valueIfFalse
"value" in listOrMap
size(list)
size(string)
"text".startsWith("te")
"text".endsWith("xt")
"text".contains("ex")
has(object.property)
hasProperty(obj, "key")
Jos jokin menee pieleen, näet jonkin seuraavista ilmoituksista:
| Virhe | Merkitys |
|---|---|
SYNTAX_ERROR | Komentosarjassa on kirjoitusvirhe, puuttuva lainausmerkki tai virheellinen operaattori |
TYPE_ERROR | Yhdistät yhteensopimattomia tyyppejä |
RUNTIME_ERROR | Komentosarja suoritettiin, mutta siinä ilmeni ongelma, kuten määrittelemätön muuttuja |
FETCH_LIMIT_EXCEEDED | Haet liian monta dokumenttia (enintään 50) |
TIMEOUT | Komentosarjan suorittaminen kesti liian kauan (enintään 5 sekuntia) |
AST_DEPTH_EXCEEDED | Lauseke on liian syvästi sisäkkäinen (enimmäissyvyys 50) |
SCRIPT_TOO_LONG | Komentosarja ylittää 5 000 merkin rajan |
CEL-moottori on suunniteltu laajennettavaksi. Tulevia suunniteltuja ominaisuuksia ovat esimerkiksi MCP-palvelinintegraatio ja tekoälyominaisuudet:
// Tulevaisuudessa: ulkoisten palveluiden kutsuminen MCP:n kautta
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)
// Tulevaisuudessa: tekoälypohjainen sisällön luonti
ai.summarize(documents.get("article", meta.params.id).body, 100)
ai.translate(meta.params.text, meta.params.targetLang)
ai.classify(meta.params.input, ["positive", "negative", "neutral"])
Ominaisuudet lisätään rekisteröidyn funktiojärjestelmän kautta siten, että olemassa olevien komentosarjojen taaksepäin yhteensopivuus säilyy.
documents. tai meta., jolloin editori näyttää käytettävissä olevat vaihtoehdotdocuments.get("schema", "id") ja lisää vasta sitten .fieldName!= null ? ... : ..., jos dokumenttia ei välttämättä oledocuments.get()- tai documents.find()-kutsu kuluttaa 50 haun rajaameta.params-arvoja meta.segments-arvojen sijaan – nimetyt parametrit validoidaan ja ne ovat luotettavampiahas()-funktiota valinnaisille parametreilledocuments.ref()-menetelmää dynaamisille tunnisteilledoc.fieldName-viittauksia nykyisen dokumentin kenttien lukemiseen lasketuissa lausekkeissaTässä osiossa käsitellään edistyneitä tapoja linkittää dokumentteja toisiinsa ja rakentaa relaatioihin perustuvia sisältörakenteita.
Yksinkertaisimmillaan yksi dokumentti viittaa toiseen tunnisteen avulla:
// Artikkeli tallentaa tekijän tunnisteen ja hakee tekijän nimen
documents.get("author", documents.get("article", "intro").authorId).name
documents.get("country", documents.get("airport", meta.params.code).countryCode).name
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name
// Lentokenttä → Maa → Alue → Maanosa
documents.get("continent",
documents.get("region",
documents.get("country",
documents.get("airport", meta.params.code).countryCode
).regionCode
).continentCode
).name
documents.translated("country",
documents.get("airport", meta.params.code).countryCode,
meta.params.lang
).name
Jokainen documents.get()-, documents.find()- ja documents.ref().get()-kutsu kirjataan välimuistin mitätöintiä varten. Kun viitattu dokumentti muuttuu, CMS tietää, mitkä CEL-lausekkeet on arvioitava uudelleen.
Seurattavia riippuvuuksia ovat:
schema:identifier – tietty dokumenttischema:identifier – sama kuin get, ketjutetulla syntaksillaschema:* – skeematason riippuvuusTässä ohjeessa luodaan monikielinen aloitussivu, johon pääsee osoitteella /{lang}/landingPage.
Luo CMS:n hallinnassa mukautettu greeting-skeema:
{
"name": "greeting",
"fields": [
{ "name": "code", "type": "string", "required": true },
{ "name": "headline", "type": "string", "required": true },
{ "name": "subheadline", "type": "string" },
{ "name": "ctaText", "type": "string" },
{ "name": "ctaUrl", "type": "string" }
]
}
Luo dokumentti jokaiselle kielelle ja lisää reitille CEL-skriptit kentille headline, subheadline, ctaText ja ctaUrl:
documents.get("greeting", meta.params.lang).headline
documents.get("greeting", meta.params.lang).subheadline
documents.get("greeting", meta.params.lang).ctaText
documents.get("greeting", meta.params.lang).ctaUrl
Määritä sivun poluksi /{lang}/landingPage, tilaksi Live ja yhdistä lang-parametri language-komponenttiin.
Lisää reitille sankarilohko ja käytä yllä olevia CEL-lausekkeita kunkin kentän arvona.
Lisää catch-all-reitti. ParametricRoutePage ratkaisee sivun, poimii URL-osoitteesta meta.params-arvot, arvioi CEL-sidonnat palvelimella ja renderöi lohkot rekisterin kautta.
// app/[...slug]/page.tsx
import ParametricRoutePage from 'cms-renderer/lib/renderer';
import { registry } from '@/lib/registry';
import { cmsConfig } from '@/lib/cms-config';
export const dynamic = 'force-static';
interface PageProps {
params: Promise<{ slug: string[] }>;
}
export default async function Page({ params }: PageProps) {
const { slug } = await params;
return (
<ParametricRoutePage
registry={registry}
apiKey={cmsConfig.apiKey}
websiteId={cmsConfig.websiteId}
cmsUrl={cmsConfig.cmsUrl}
params={Promise.resolve({ slug })}
/>
);
}
Avaa seuraavat URL-osoitteet nähdäksesi lokalisoidun sisällön:
| URL | Odotettu otsikko |
|---|---|
/ko/landingPage | 환영 |
/en/landingPage | Tervetuloa |
/ja/landingPage | いらっしゃいませ |
Kun käyttäjä avaa /ko/landingPage-osoitteen, CMS täsmäyttää reitin, poimii meta.params.lang = "ko" -arvon, validoi sen, suorittaa CEL-lausekkeet ja palauttaa lokalisoidut lohkot asiakkaalle.
interface CelMeta {
/** Nykyinen kielialuekoodi, esimerkiksi 'en-US' */
locale: string;
/** URL-osoitteesta poimitut reittiparametrit */
params: Record<string, string>;
/** URL-polun osat */
segments: string[];
/** Nykyisen dokumentin tunniste */
docId: string | null;
/** Nykyisen dokumentin otsikko */
title: string;
}
extractParams-funktio käsittelee URL-polut seuraavasti:
Malli: /{country}/{lang}/products
Polku: /us/en/products
Algoritmi:
1. Normalisoi molemmat (poista lopun kauttaviivat)
2. Jaa osiin
3. Varmista, että osien määrät täsmäävät
4. Poimi dynaamiset osat parametreiksi
5. Palauta: { country: "us", lang: "en" }
{ "lang": "language" }
{
"lang": {
"schemaName": "language",
"slugField": "code"
},
"slug": {
"schemaName": "article",
"slugField": "slug"
}
}
Kun käytetään kutsua documents.get(schema, identifier):
id-kentälläcontent.codecontent.slugtitle-kenttäNäin dokumentteihin voidaan viitata joustavasti millä tahansa yksilöllisellä tunnisteella.