Docs LATEST

Page Service

Load, cache, list, save, and delete file-native pages through a single service.

Content & Data

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/URL
  • title - page title
  • content - 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.