Data Layer
SynaptikCMS uses a split-file architecture: each content item is stored in its own JSON file, with a lightweight index per type for fast loading without reading every item.
Two layers, two responsibilities
| File | Function prefix | Role |
|---|---|---|
data-layer.php | sl_ | Read-only — index, items, categories, tags, internal cache |
admin-data-layer.php | sl_admin_ | Write — save item, update index, delete, save categories/tags |
The read layer maintains an internal cache in $GLOBALS['_sl_cache'] to avoid re-reading files multiple times per request. The write layer invalidates this cache after every operation.
Index vs. full item
Lightweight index (_index.json) — loaded on every request. Contains metadata only:
_file, slug, custom_slug, title, date, category, tags, image, show_in_menu, menu_order
Additional per-type fields: articles → summary, show_on_homepage; projects → description, show_on_homepage; pages → page_template.
Full item file ({slug}.json) — loaded only for single-item views. Contains everything: HTML content, SEO fields, galleries, show_date, show_title, og_image, etc.
How index.php loads data
Step 1 — Lightweight index for all types (always):
$data = sl_build_data_array(['article', 'page', 'project'], false);
$GLOBALS['data'] = $data;
Step 2 — Full item for single-item views:
// On /article/my-slug/
$data['article'] = [$fullItem]; // Overwrites the index with a single full item
$GLOBALS['data'] = $data;
$data[$type] is volatile. On list pages it contains the full index. On single-item pages it contains only that one item. Never assume $GLOBALS['data']['article'] holds all articles — use slloadindex('article') when you need the full catalogue.
Read layer functions (sl_*)
sl_load_index(string $type): array
Load and return the lightweight index for a type ('article', 'page', 'project'). Result is cached for the full request.
sl_load_item(string $type, string $fileSlug): array
Load full data for an item from its individual file. $fileSlug is the _file field from the index.
sl_load_item_by_slug(string $type, string $effectiveSlug): ?array
Load a full item by its public slug (custom_slug ?: slug). Used by the router.
sl_load_all_items(string $type): array
Load all full items for a type. Expensive — use only when content bodies are needed (search, SEO overview, sitemap).
sl_load_categories(): array
Load the category store. Result is cached.
sl_load_tags(): array
Load the tag store. Result is cached.
sl_build_data_array(array $types, bool $fullItems = false): array
Build the legacy-compatible $data array.$fullItems = false → lightweight index.$fullItems = true → full items.
sl_effective_slug(array $item): string
Return custom_slug ?: slug for an item or index entry.
sl_file_slug(array $entry): string
Return the _file slug from an index entry (JSON filename without .json).
sl_find_in_index(string $type, string $effectiveSlug): ?array
Search an index for an entry by public slug. Returns [entry, position] or null.
