Page Service
Load, cache, list, save, and delete file-native pages through a single service.
PageService is the main API for page operations in Core. It wraps the content driver, dispatches lifecycle events, and handles page caching and list cache invalidation.
Getting the Service #
$pages = app('pages');
// or
$pages = app(PageService::class);
Loading Pages #
Single Page #
use VelvetCMS\Exceptions\NotFoundException;
try {
$page = $pages->load('about');
echo $page->title;
echo $page->html(); // Rendered HTML
} catch (NotFoundException $e) {
// Page does not exist
}
Returns a Page object. Throws NotFoundException if the page doesn't exist.
With Caching #
When the driver can provide a last-modified timestamp, PageService caches page loads by slug and mtime. Saving or deleting the page clears the stale entry.
// First call: loads from driver, caches result
$page = $pages->load('about');
// Subsequent calls: served from cache
$page = $pages->load('about');
Listing Pages #
Basic List #
$allPages = $pages->list();
Returns a Collection of Page objects.
With Filters #
$published = $pages->list([
'status' => 'published',
]);
$drafts = $pages->list([
'status' => 'draft',
]);
Sorting #
$pages->list([
'order_by' => 'created_at',
'order_dir' => 'desc',
]);
$pages->list([
'order_by' => 'title',
'order_dir' => 'asc',
]);
Pagination #
// Get first 10 pages
$firstPage = $pages->list([
'limit' => 10,
'offset' => 0,
]);
// Get next 10 pages
$secondPage = $pages->list([
'limit' => 10,
'offset' => 10,
]);
Combined Filters #
$recentPublished = $pages->list([
'status' => 'published',
'order_by' => 'created_at',
'order_dir' => 'desc',
'limit' => 5,
]);
Saving Pages #
use VelvetCMS\Models\Page;
$page = new Page(
slug: 'new-post',
title: 'My New Post',
content: '# Hello\n\nThis is my new post.',
status: 'draft',
layout: 'blog',
);
$pages->save($page);
Required Fields #
slug- unique identifier/URLtitle- page titlecontent- raw page body
Updating Existing Pages #
Save with the same slug to update:
$page = $pages->load('existing-page');
$page->title = 'Updated Title';
$page->status = 'published';
$pages->save($page);
Deleting Pages #
use VelvetCMS\Exceptions\NotFoundException;
try {
$pages->delete('old-page');
} catch (NotFoundException $e) {
// Page did not exist
}
Returns true on success. Throws NotFoundException if the page doesn't exist.
Events #
PageService fires events for each operation:
| Event | Payload | When |
|---|---|---|
page.loading |
string $slug |
Before loading |
page.loaded |
Page $page |
After loading |
page.saving |
Page $page |
Before saving |
page.saved |
Page $page |
After saving |
page.deleting |
string $slug |
Before deleting |
page.deleted |
string $slug |
After deleting |
Example: Auto-Generate Slug #
$events->listen('page.saving', function (Page $page) {
if (empty($page->slug)) {
$page->slug = slugify($page->title);
}
});
Example: Clear Cache on Save #
$events->listen('page.saved', function (Page $page) {
app('cache.tags')->flush('pages');
});
In practice, PageService already flushes the tagged list cache on save and delete. Custom listeners are most useful for search indexing, webhooks, audit trails, or cross-service notifications.
Convenience Methods #
PageService also exposes a few focused helpers:
$pages->exists('about');
$pages->published();
$pages->drafts();
$pages->recent(10);
$pages->count(['status' => 'published']);
These all delegate to the same underlying indexed file driver.
The Page object #
The returned Page model exposes the fields and helpers you will use most often:
use VelvetCMS\Models\Page;
$page = new Page(
slug: 'about',
title: 'About Us',
content: '# About Us\n\nOriginal markdown...',
status: 'published',
layout: 'default',
excerpt: 'Learn more about our company.',
meta: [], // Custom frontmatter fields
createdAt: new DateTime(),
updatedAt: new DateTime(),
publishedAt: new DateTime(),
);
$page->html(); // Rendered HTML
$page->isPublished(); // true
$page->getExcerpt(160); // Auto-generated excerpt if not set
$page->getMeta('key'); // Access custom meta fields
$page->toArray(); // Convert to array representation
For the full service and model API surface, see the API reference page for PageService.
Supported list filters #
The built-in file driver understands these filters through the page index:
| Filter | Description |
|---|---|
status |
draft or published |
limit |
Maximum number of rows |
offset |
Offset into the result set |
order_by |
created_at, updated_at, published_at, slug, title, or status |
order_dir |
asc or desc |
In practice #
Most app code ends up using PageService in one of three ways:
- loading a single page by slug
- listing published pages for an index or feed
- saving or publishing pages through CLI or editorial tooling
If you find yourself needing lower-level storage details, that is usually the point where the Page Indexing guide or the API reference becomes the right document instead of this guide.