Collections & Content
Collections are the heart of ZephyrPHP. Create any content type — blog posts, products, events, portfolios — with custom fields, relations, and workflows.
What Are Collections?
A collection is a content type you define through the CMS admin panel. Each collection gets its own database table, entry list, and editor form — all generated automatically from the fields you configure.
Creating a Collection
- Go to CMS Admin > Collections
- Click Create Collection
- Enter a name (e.g., "Blog Posts") — slug auto-generates (e.g., "blog_posts")
- Configure options:
- Enable REST API — expose entries via API endpoints
- Publishable — adds draft/published status and scheduled publishing
- Enable Slug Field — adds a URL-friendly slug to each entry
- SEO Meta Fields — adds meta title, description, OG tags per entry
- Public Submit — allow visitors to submit entries via frontend forms
- Translatable — enable multi-language entries
- Save — your collection is ready for fields
Field Types
Add fields to define the structure of your content:
| Field Type | Database Column | Use Case |
|---|---|---|
| Text | VARCHAR(255) | Titles, names, short text |
| Textarea | TEXT | Descriptions, excerpts |
| Rich Text | LONGTEXT | Full content with HTML formatting |
| Number | INT | Quantities, ratings, order |
| Decimal | DECIMAL(10,2) | Prices, measurements |
| Boolean | TINYINT | Toggles (featured, active) |
| Date | DATE | Event dates, deadlines |
| Date & Time | DATETIME | Timestamps, scheduling |
| VARCHAR(255) | Email addresses | |
| URL | VARCHAR(255) | Website links |
| Select | VARCHAR(255) | Dropdown choices (status, category) |
| Image | VARCHAR(500) | Featured images, thumbnails |
| File | VARCHAR(500) | Document uploads (PDF, etc.) |
| Slug | VARCHAR(255) | URL-friendly identifier — auto-becomes the slug source field |
| JSON | JSON | Structured data, metadata |
| Relation | INT / JOIN table | Link to other collections (author, category) |
The Slug Field Type
When you enable "Enable Slug Field" on a collection and add a field with type Slug, that field automatically becomes the slug source. The system generates URL-friendly slugs from that field's value for each entry.
For example, if you have a "Title" field of type Slug and enter "Hello World", the entry's slug becomes hello-world.
If you enable slugs but haven't added a Slug-type field, a yellow warning appears in the Fields tab directing you to add one.
Relation Fields
Link entries across collections using three relation types:
- One to One — Each entry links to one entry in the related collection
- One to Many — Each entry links to multiple entries
- Many to Many — Entries in both collections can link to each other (uses a join table)
When adding a Relation field, select the related collection and a display field (the field shown as the label in the entry editor).
System Fields
Every collection automatically includes:
| Field | Type | Description |
|---|---|---|
id | Integer or UUID | Primary key (auto-increment or UUID, chosen at creation) |
slug | VARCHAR(255) | URL-friendly identifier (when enabled) |
created_by | Integer | User who created the entry |
created_at | DateTime | Creation timestamp |
updated_at | DateTime | Last update timestamp |
status | String | Draft/Published (when publishable) |
published_at | DateTime | Publish date (when publishable) |
Managing Entries
Go to Collections > [Collection Name] > View Entries to manage content:
- Create — Fill out the auto-generated form with your custom fields
- Edit — Update any entry's fields, status, or SEO metadata
- Delete — Remove entries individually or in bulk
- Search & Filter — Search by any searchable field, sort by any sortable field
- Bulk Actions — Publish, unpublish, or delete multiple entries
- Import/Export — CSV and JSON import/export with field mapping
- Saved Views — Save filter/sort presets for quick access
- Entry History — View and restore previous revisions
Frontend Routing
Set a URL Prefix on a collection to auto-register frontend routes:
/prefix— List page showing paginated entries/prefix/{slug}— Detail page showing a single entry
For example, setting URL prefix to blog creates /blog (listing) and /blog/hello-world (detail).
Querying Collections in Templates
Use the collection() and entry() Twig functions to display content:
{# List entries #}
{% set posts = collection('blog_posts', {per_page: 6, sort_dir: 'DESC'}) %}
{% for item in posts.data %}
<h3>{{ item.title }}</h3>
<p>{{ item.excerpt|striptags|slice(0, 120) }}</p>
{% endfor %}
{# Single entry #}
{% set post = entry('blog_posts', 'hello-world') %}
<h1>{{ post.title }}</h1>
{{ post.content|raw }}
See the Twig Reference for all available functions and options.
SEO Fields
Enable SEO on any collection to add meta title, meta description, and Open Graph fields to every entry. Use the SEO Twig functions in your templates:
{{ seo_meta(item, 'blog_posts') }}
{{ og_tags(item, 'blog_posts') }}
{{ json_ld(item, 'blog_posts') }}
Content Workflows
Enable workflows on the Workflow tab to require entries to pass through approval stages before publishing. Define custom stages (e.g., draft → review → approved → published) and assign reviewers per stage.
API Access
Enable API access per collection to expose entries via REST endpoints:
GET /api/cms/{collection}— List entries with paginationGET /api/cms/{collection}/{id}— Get single entryPOST /api/cms/{collection}— Create entryPOST /api/cms/{collection}/{id}— Update entryPOST /api/cms/{collection}/{id}/delete— Delete entry
Configure rate limiting from the collection settings. See the REST API docs for authentication details.
Public Form Submission
Enable "Public Submit" to let visitors submit entries from the frontend. Use the Twig helper to render a form:
{{ render_collection_form('contact_form') }}
Configure submission settings: success message, redirect URL, email notifications, honeypot bot protection, and rate limiting per IP.
CMS system tables use the cms_ prefix. User-created collection tables use the app_ prefix (e.g., app_blog_posts) to keep them clearly separated.