The Elements CMS is a powerful content management system designed for RapidWeaver elements, providing a flexible and efficient way to manage content through markdown files with YAML front matter.
To initialize the CMS in your PHP code:
require_once 'path/to/cms.php';
// Initialize CMS with base path and options
$cms = cms('/path/to/content', [
'detailPageUrl' => 'https://example.com/posts',
'prettyUrls' => true
]);
Collections are groups of content items stored in markdown files. Each collection is stored in a directory, with each item represented by a markdown file.
Items are individual content pieces stored as markdown files with YAML front matter. The filename format can be either:
YYYY-MM-DD-slug.md
(for dated content)
slug.md
(for undated content)
Example item structure:
---
title: My Post Title
date: 2024-03-20
author: John Doe
tags: [news, technology]
categories: [blog]
featured: true
status: published
image:
type: remote
src: https://example.com/image.jpg
alt: Image description
width: 800
height: 600
---
Content goes here...
// Get a collection
$collection = $cms->collection('blog');
// Filter collection
$filtered = $collection->filter([
'status' => 'published',
'featured' => true
]);
// Order collection
$ordered = $collection->orderBy('date', 'desc');
// Paginate results
$paginated = $collection->paginate(1, 10);
// Date-based filtering
$collection->whereDate('date', '>=', '2024-01-01');
// Custom filtering
$collection->filterWith(function($item) {
return $item->featured() && $item->status() === 'published';
});
// Load a specific item
$item = $cms->item('blog/my-post');
// Access item properties
$title = $item->title();
$date = $item->date('F j, Y');
$body = $item->body();
$excerpt = $item->excerpt(30);
$image = $item->image();
$url = $item->url();
// Access custom metadata
$customField = $item->meta('custom_field');
// Load item with relationships
$item = $cms->item('blog/my-post')
->with('author', 'categories')
->withOne('featured_image')
->loadRelations();
// Access relationships
$author = $item->author;
$categories = $item->categories;
$featuredImage = $item->featured_image;
The CMS includes a powerful search system that can be used in two ways:
// Search within a collection
$results = $collection->search('search term');
// The search results are scored based on where matches are found:
// - Title matches: 10 points
// - Excerpt matches: 5 points
// - Body matches: 1 point
// - Tag matches: 3 points per matching tag
// Results are automatically sorted by score in descending order
The CMS provides a search endpoint at search.php
that accepts the following parameters:
q
: Search query
collectionPath
: Path to the collection
detailPageUrl
: URL for detail pages
prettyUrls
: Whether to use pretty URLs
basePath
: Base path for content
template
: HTML template for rendering results, can include Twig syntax
Example AJAX call:
// Alpine snippet
this.template = this.$el.querySelector(
'[data-template="cmsCollectionSearchItemsTemplate"]'
).innerHTML;
const params = new URLSearchParams({
q: this.query,
collectionPath: "{{collectionDir.href}}",
detailPageUrl: "{{detailPage.href}}",
prettyUrls: "{{prettyUrls}}",
basePath: "<?= __DIR__ ?>",
template: this.template,
});
const res = await fetch(`{{cmsPath}}/search.php?${params}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
The search system automatically maintains an index file (search-index.json
) in the collection directory for improved performance. The index is automatically rebuilt when content changes are detected.
The CMS provides a fluent interface for finding related items:
$related = $item->related()
->byTags()
->limit(5)
->excludeSelf()
->get();
// Or find by multiple criteria
$related = $item->related()
->by(['tags', 'author', 'categories'])
->in('blog')
->limit(3)
->get();
$rss = $collection->toRss(
'My Blog',
'Latest posts from my blog',
'https://example.com/blog'
);
$sitemap = $collection->toSitemap(
'https://example.com',
'weekly',
0.8
);
File Organization
Keep collections in separate directories
Use consistent naming conventions for files
Include all necessary metadata in front matter
Performance
Use caching when appropriate
Implement pagination for large collections
Optimize search queries
Content Structure
Use consistent front matter fields
Include required metadata (title, date, status)
Properly format markdown content
Security
Validate user input
Sanitize output
Use proper file permissions
The CMS requires the following PHP packages:
Symfony YAML
CommonMark
Illuminate Collections
Twig (for template rendering)
The CMS includes built-in error handling for common scenarios:
Invalid file paths
Missing required metadata
Malformed YAML front matter
Search index issues
For issues, feature requests, or contributions, please refer to the project's issue tracker or documentation repository.
The ElementsCMS class is a PHP-based content management system that provides functionality for managing CMS collections and items. It serves as the main entry point for interacting with content stored
The ElementsCMS class manages the base path for content storage and provides methods to create collections, load items, and manage configuration options.
__construct(string $basePath, array $options = [])
Creates a new instance of ElementsCMS.Parameters:
$basePath (string)
: The base path for the CMS content storage
$options (array, optional)
: Additional configuration options for the CMS
$cms = new ElementsCMS('/path/to/content', ['debug' => true]);
make(string $basePath, array $options = []): ElementsCMS
Static factory method that creates a new instance of ElementsCMS.Parameters:
$basePath (string): The base path for the CMS content storage
$options (array, optional): Additional configuration options for the CMS
Returns: ElementsCMS instance
$cms = ElementsCMS::make('/path/to/cms_data');
basePath(): string
Returns: The base path as a string
$path = $cms->basePath(); // Returns '/path/to/content'
options(): array
Returns: Array of all options
$allOptions = $cms->options();
option(string $key, $default = null): mixed
Returns: The option value or default value
Parameters:
$key (string)
: The option key to retrieve
$default (mixed, optional)
: Default value returned if the option is not set
$debug = $cms->option('debug', false);
$theme = $cms->option('theme', 'default');
setOption(string $key, $value): void
Sets an option value.
$key (string)
: The option key to set
$value (mixed)
: The value to set
$cms->setOption('debug', true);
$cms->setOption('cache_enabled', false);
collection(string $path, array $options = []): ElementsCMSCollection
Creates a new collection instance.Parameters:
$path (string): The path for the collection (relative to base path)
$options (array, optional): Additional options for the collection
Returns: ElementsCMSCollection instance
$articles = $cms->collection('articles', ['sort' => 'date']);
$projects = $cms->collection('projects');
item(string $collectionPath, string $slug): ?ElementsCMSItem
Loads a specific item from a collection.Parameters:
$collectionPath (string)
: The path of the collection
$slug (string)
: The slug/filename of the item (without .md extension)
Returns: ElementsCMSItem instance or null if not found
$blogPost = $cms->item('blog', 'my-first-post');
$aboutPage = $cms->item('pages', 'about');
<?php
require_once '/path/to/ElementsCMS.php';
$cms = ElementsCMS::make(
'/var/www/cms_data',
['debug' => true, 'cache_ttl' => 3600]
);
// Create a blog collection
$blog = $cms->collection('blog', ['sort' => 'date_desc']);
// Create a pages collection
$pages = $cms->collection('pages');
// Load a specific blog post
$post = $cms->item('blog/introduction-to-cms');
// Load a page
$homepage = $cms->item('pages/home');
// Get configuration
$debugMode = $cms->option('debug', false);
$cacheEnabled = $cms->option('cache_enabled', true);
// Set configuration
$cms->setOption('theme', 'custom');
$cms->setOption('max_items_per_page', 10);
This class requires the following files:
ElementsCMSCollection.php
ElementsCMSItem.php
Make sure these files are available in the same directory as the ElementsCMS class.
The CMS expects content to be organized in the following structure:
cms-base-path/
collection-name/
item-slug.md
another-item.md
another-collection/
item1.md
item2.md
Items must be in Markdown files (.md extension) within collection directories.
A collection class for managing CMS items, providing methods for filtering, ordering, pagination, and searching.
__construct(ElementsCMS $cms, string $path, array $options = [])
Creates a new collection instance.
$cms (ElementsCMS
): The CMS instance.
$path (string
): Path to the collection (folder).
$options (array
): Additional options for the collection.
with(string ...$relations): self
Add relations to be eager-loaded for all items in the collection.
$relations (string ...
): One or more relation names.
Returns: $this
(for chaining)
filter(array $criteria = []): self
Filter items in the collection by key/value pairs.
$criteria (array
): Associative array of criteria (e.g., ['status' => 'published']
)
Returns: $this
(for chaining)
filterWith(callable $callback): self
Filter items in the collection using a custom callback.
$callback (callable
): Function that receives an item and returns true
to keep, false
to exclude.
Returns: $this
(for chaining)
orderBy(string $field, string $direction = 'desc'): self
Order the collection by a specified field.
$field (string
): Field name to order by.
$direction (string
): 'asc'
or 'desc'
(default: 'desc'
)
Returns: $this
(for chaining)
whereDate(string $field, string $operator, string $date): self
Filter items by date field using a comparison operator.
$field (string
): Date field to compare (e.g., 'published_date'
)
$operator (string
): Comparison operator (e.g., '>='
, '=='
, '<'
)
$date (string
): Date value for comparison.
Returns: $this
(for chaining)
paginate(int $page = 1, int $perPage = 10): array
Paginate the collection.
$page (int
): Page number (default: 1
)
$perPage (int
): Items per page (default: 10
)
Returns: array
— Paginated results, typically including items
, total
, page
, per_page
, etc.
getCollection(): LaravelCollection
Returns the underlying Laravel collection of items.
Returns: Illuminate\Support\Collection
of ElementsCMSItem
objects.
findBySlug(string $slug): ?ElementsCMSItem
Find an item in the collection by its slug.
$slug (string
): The slug to search for.
Returns: ElementsCMSItem|null
search(string $query): array
Search the collection items by query string.
$query (string
): The search term.
Returns: array
— Array of matching ElementsCMSItem
objects.
$collection = new ElementsCMSCollection($cms, 'posts', [
'expectDates' => true
]);
// Filter, order, and paginate items
$results = $collection
->filter(['status' => 'published'])
->orderBy('published_date', 'desc')
->paginate(1, 10);
// Find a specific item by slug
$item = $collection->findBySlug('hello-world');
// Search items
$matches = $collection->search('static site generator');
Represents a single CMS item loaded from a Markdown file with front matter. Provides structured access to metadata, raw and rendered content, file paths, and relationships to other items.
__construct(ElementsCMS $cms, array $data = [])
Creates a new CMS item.
$cms (ElementsCMS
): The CMS instance.
$data (array
): The data for the CMS item.
static load(ElementsCMS $cms, string $filepath): ?self
Load a CMS item from a file.
$cms (ElementsCMS
): The CMS instance.
$filepath (string
): Path to the file.
Returns: ElementsCMSItem|null
– Loaded item or null if not found.
setOptions(array $options): self
Sets runtime options for the item.
$options (array
): Option key/value pairs.
Returns: $this
for method chaining.
getOption(string $key, $default = null)
Gets an option value by key.
$key (string
): Option name.
$default (mixed
): Default value if not found.
Returns: Mixed option value.
slug(): string
Returns the item’s slug (URL-friendly identifier).
title(): string
Returns the item’s title.
date(string $format = 'F j, Y'): string
Returns the item's date in the given format.
$format (string
): Date format (default 'F j, Y'
).
datePublished(string $format = 'F j, Y'): string
Returns the item's published date.
dateModified(string $format = 'F j, Y'): string
Returns the item's last modified date.
featured(): bool
Checks if the item is marked as featured.
status(): string
Returns the item's status (e.g., published/draft).
body(): string
Returns the rendered HTML body content.
rawBody(): string
Returns the raw markdown body content.
image(): ?string
Returns the item's image URL, if available.
excerpt(int $words = 30): string
Returns an excerpt of the body, limited to the specified word count.
meta(string $key, $default = null): mixed
Fetches a value from the item's metadata/front-matter.
$key (string
): Meta key.
$default (mixed
): Default if key is missing.
attach(string $key, $value): self
Attach related data to the item (e.g., relations, computed properties).
get(string $key, $default = null): mixed
Returns any value from the item data or metadata.
__call($method, $arguments)
Allows dynamic method access to metadata fields.
file(): string
Returns the full path to the file.
fileName(): string
Returns the base filename (without extension).
url(): string
Returns the item’s URL.
lastModified(string $format = 'F j, Y'): string
Returns the file's last modified date.
toArray(): array
Returns all item data as an associative array.
with(string ...$relations): self
Declare relations (one-to-one or one-to-many) to eager-load.
withOne(string ...$relations): self
Declare one-to-one relations to eager-load.
withMany(string ...$relations): self
Declare one-to-many relations to eager-load.
loadRelations(): self
Loads all defined relations for the item.
$cms = new ElementsCMS(/* ... */);
$item = ElementsCMSItem::load($cms, 'posts/hello-world');
if ($item) {
echo $item->title(); // Item title
echo $item->body(); // Rendered body
echo $item->datePublished(); // Published date
$item->with('author', 'categories')->loadRelations();
}