objects

Page

A page on the site.

Routes its own URLs, renders its view, and exposes its fields, children, parents and files to templates.

$page Phlat\Page extends Record 76 methods
Properties (14)
$page->router Router readonly
$page->view ?string readonly
$page->published bool readonly Whether this page is live - true unless _index.json says false.
$page->access string readonly Who may open this page: '' for anyone, 'login' for any signed-in user, or role names joined by '|'.
$page->hidden bool readonly Whether this page is left out of navigation and child lists.
$page->position int readonly Where this page sits among its siblings when its parent's view sorts by `position` - set by dragging it in the admin tree.
$page->uri string readonly
$page->path string readonly
$page->objectRoot string readonly
$page->uuid string readonly
$page->locked bool readonly
$page->created ?int readonly
$page->updated ?int readonly
$page->isRoot bool readonly
Show

Identity 8

  • fragment Whether this page renders as a bare fragment - its own _index.json wins over the view's default.
  • objectType Always `page`.
  • boundClass The class App::loadType() looks for when views/{name}/{name}.php declares a bound subclass, e.g. "article" -> ArticlePage.
  • registryKeyFor Builds a page registry key from a raw page uuid, for callers without a live Page instance.
  • registryPath The path stored in the registry for this object.
  • registryFields Extra registry columns this object type contributes (e.g. view for pages, role for users).
  • isVirtual Whether this page's view says `"virtual": true`: its pages come from a source page, never from the registry.
  • virtual A virtual child of this source page: $data from the source, with the overlay folder at its URL (if any) over it.

Saving 3

  • save Persists page data, routing structural fields to _index.json and content fields to _data.json.
  • delete Deletes this page and its persisted subtree - PageCollection::delete() for one page, which has the details.
  • move Moves (or renames) this page and its whole subtree to $newPath, e.g. "blog/2026/post".

Fields 6

  • fields Returns this page's template fields as resolved FieldValue instances.
  • settingFields The structural settings an editor sets - published, access, hidden, locked - as FieldValues, so the admin edits them with the same field UI as everything else.
  • childFields The fields a new child is made from: its name, unless this view names pages by uuid, and its view when there is a choice.
  • viewFields The view a page without one is given: the ones its parent's view takes, or any when it names none.
  • moveFields The fields a move is made from: the page's name and its parent, any page whose view takes this one's (or where it is now).
  • viewConfig Returns app-level config under $key merged with this view's override of the same key.

Drafts 4

  • hasAutosave Whether an unsaved draft exists for this page.
  • autosave Persists a draft snapshot outside the normal save path - no _index.json, no registry, no git.
  • discardAutosave Clears any pending draft.
  • data The page's content file.

Rendering 6

  • view The view that renders this page; throws when the page has none.
  • session Session data scoped to this page's own view - auto-namespaced, no manual scope('name') needed.
  • emit Fires `{view}/{event}`, this page's own view as the prefix, so a page can't spell a core event (core names have no slash).
  • controller Includes a view's controller file and calls it if it returns a callable; returns the resulting data array.
  • render Renders the page view, merging in global and view-specific controller data.
  • cache This page's part of the fragment cache.

Access 3

  • isPublic Whether anyone at all may open this page - it and every ancestor published and open to all - whoever is asking.
  • isViewable Whether the current visitor may open this page.
  • assertViewable Throws what the current visitor gets for a page they may not open: a 404 for an unpublished one (it doesn't admit to existing), a login redirect for a gated page when signed out, a 403 when signed in without the role.

Routing 5

  • route Dispatches the request sub-path against this page's view router.
  • remainder Returns the request path after stripping this page's own URL prefix, trimmed of slashes.
  • target Resolves remainder() as a Page, the common case behind most remainder() call sites.
  • segment Returns the nth segment (1-indexed) of the request sub-path, or null.
  • url Returns the site-relative URL by stripping the pages/ root from the filesystem path.

Tree 18

  • parent Returns the parent page, or null if this page has no parent (including root pages).
  • parents Returns all ancestor pages from root to immediate parent, lazily computed and cached.
  • closest Returns the nearest page matching $query (the find() DSL) walking up from this page, this page included, or null if none does.
  • root Returns the root page.
  • section Returns the top-level section page.
  • depth Returns the depth in the page tree. 0 for root pages.
  • childDepth The depth new children are placed at: one below this page, or deeper when its view's `children.path` puts them in folders.
  • reorderable Whether this page's children are put in order by hand: its view's `children.sort` is `position`.
  • childViews The views an editor may give a new child: the view's `children.views`.
  • siblings Returns sibling pages - children of the parent, excluding this page.
  • next Returns the next sibling in parent's child order, or null if this is the last.
  • prev Returns the previous sibling in parent's child order, or null if this is the first.
  • contains True if $other is this page or a descendant of it.
  • hasChildren True if this page has any children.
  • isActive True if this page is the current request page.
  • isOpen True if this page is active or contains the active page.
  • child Returns a named child page without checking whether it exists.
  • has Whether a child page folder already exists on disk.

Children 6

  • new Creates a new child page: mints its uuid and writes a complete, minimal _index.json in one shot, then applies $data via the normal save() path - structural keys (view/hidden/ published/locked) to _index.json, everything else to _data.json (only written if there's content).
  • children Queries the registry for direct child pages, ordered by the view's own `children.sort` (_index.json), unless $query supplies its own sort= to override it.
  • pageLimit The page size: $limit, else the view's `pagination.limit` over the app's. 0 means no limit.
  • paginate The current `?page=N` slice of children($query); every child when the limit is 0.
  • pageCount How many pages children($query) fill at the page limit; 1 when the limit is 0.
  • find Queries the registry for pages within this page's subtree.

Files 5

  • fileSourcePath Folder a file() call mirrors source files from.
  • publicPath Returns this page's public-mirror directory, e.g. "" -> public/, "blog/post" -> public/blog/post.
  • file Resolves a file from this page's own folder.
  • image Resolves an image from this page's own folder.
  • files This page's files, narrowed by the query DSL over filename, name, extension, type, mime, size, modified and their metadata fields: `files('type=image,sort=filename,limit=4')`.

From Record 12

  • assertUnlocked A locked record is protected: it can't be changed or deleted until `locked` is turned off.
  • create The one way a record comes into being: under the lock for $key (default: the path) $guard refuses a conflict, then $make builds the record at $path and save() applies $data.
  • exists Whether the record is on disk.
  • generateUuid The current system uuid format - the single source of truth for tooling that needs to mint or recognize one.
  • index The `_index.json` file: uuid, timestamps and the type's structural keys.
  • isSiteObject Whether it lives in the site rather than in `phlat/` or an addon.
  • keyFor Builds a registry uuid key from a type and identity value, e.g. keyFor('page', $uuid) -> "page:{uuid}".
  • name The folder name: the last segment of a page's URL, or a username.
  • path The record's folder, with a trailing slash.
  • publishedData The canonical _data.json contents, bypassing any draft/preview override (e.g.
  • registryKey The registry's uuid key for this object, e.g. "page:{uuid}".
  • upload Validates and stores an uploaded file (a raw $_FILES-shape array) into this record's own folder.

Identity

$page->fragment(): bool

Whether this page renders as a bare fragment - its own _index.json wins over the view's default.

Returns bool

phlat/src/Page.php:74
$page->objectType(): string

Always `page`.

Returns string

phlat/src/Page.php:80

boundClass

static
Page::boundClass(string $name): string

The class App::loadType() looks for when views/{name}/{name}.php declares a bound subclass, e.g. "article" -> ArticlePage.

Nested/hyphenated names normalize to the same class: "catalogue/record" and "catalogue-record" both -> CatalogueRecordPage.

Parameters (1)
$name string

Returns string

phlat/src/Page.php:87
Page::registryKeyFor(string $uuid): string

Builds a page registry key from a raw page uuid, for callers without a live Page instance.

Parameters (1)
$uuid string

Returns string

phlat/src/Page.php:107
$page->registryPath(): string

The path stored in the registry for this object.

Returns string

phlat/src/Page.php:112
$page->registryFields(): array

Extra registry columns this object type contributes (e.g. view for pages, role for users).

Returns array

phlat/src/Page.php:117
$page->isVirtual(): bool

Whether this page's view says `"virtual": true`: its pages come from a source page, never from the registry.

Returns bool

phlat/src/Page.php:135
$page->virtual(string $name, array $data): Page

A virtual child of this source page: $data from the source, with the overlay folder at its URL (if any) over it.

Parameters (2)
$name string
$data array

Returns Page

phlat/src/Page.php:141

Saving

$page->save(array $data = []): Page

Persists page data, routing structural fields to _index.json and content fields to _data.json.

Parameters (1)
$data array = []

Returns Page

phlat/src/Page.php:161
$page->delete(): void

Deletes this page and its persisted subtree - PageCollection::delete() for one page, which has the details.

phlat/src/Page.php:208
$page->move(string $newPath): Page

Moves (or renames) this page and its whole subtree to $newPath, e.g. "blog/2026/post".

Refuses a locked page or locked descendant, a destination that exists or has no parent page, and a move into itself. Drops the image variants recorded under the old URL, since both their rows and their public mirrors would otherwise outlive the page there, then re-indexes the old and new subtrees. Returns the page at its new path.

Parameters (1)
$newPath string

Returns Page

phlat/src/Page.php:220

Fields

$page->fields(): FieldValueSet

Returns this page's template fields as resolved FieldValue instances.

Returns FieldValueSet

phlat/src/Page.php:270
$page->settingFields(): FieldValueSet

The structural settings an editor sets - published, access, hidden, locked - as FieldValues, so the admin edits them with the same field UI as everything else.

Built here because their values come from _index.json rather than _data.json and so never appear in fields(). A locked page only accepts the lock toggle, so the rest are read-only until it is turned off.

Returns FieldValueSet

phlat/src/Page.php:285
$page->childFields(): FieldValueSet

The fields a new child is made from: its name, unless this view names pages by uuid, and its view when there is a choice.

Returns FieldValueSet

phlat/src/Page.php:318
$page->viewFields(): FieldValueSet

The view a page without one is given: the ones its parent's view takes, or any when it names none.

Returns FieldValueSet

phlat/src/Page.php:333
$page->moveFields(): FieldValueSet

The fields a move is made from: the page's name and its parent, any page whose view takes this one's (or where it is now).

Returns FieldValueSet

phlat/src/Page.php:340
$page->viewConfig(string $key): array

Returns app-level config under $key merged with this view's override of the same key.

Parameters (1)
$key string

Returns array

phlat/src/Page.php:359

Drafts

$page->hasAutosave(): bool

Whether an unsaved draft exists for this page.

Returns bool

phlat/src/Page.php:367
$page->autosave(array $data): void

Persists a draft snapshot outside the normal save path - no _index.json, no registry, no git.

Parameters (1)
$data array
phlat/src/Page.php:373
$page->discardAutosave(): void

Clears any pending draft.

Called automatically on a real save.

phlat/src/Page.php:382
$page->data(): DataFile

The page's content file.

The admin preview reads the editor's draft in its place.

Returns DataFile

phlat/src/Page.php:392

Rendering

$page->view(): PageView

The view that renders this page; throws when the page has none.

Returns PageView

phlat/src/Page.php:407
$page->session(): Session

Session data scoped to this page's own view - auto-namespaced, no manual scope('name') needed.

Returns Session

phlat/src/Page.php:415
$page->emit(string $event, mixed ...$args): void

Fires `{view}/{event}`, this page's own view as the prefix, so a page can't spell a core event (core names have no slash).

Parameters (2)
$event string
...$args mixed
phlat/src/Page.php:421
$page->controller(string $viewName, array $context = []): array

Includes a view's controller file and calls it if it returns a callable; returns the resulting data array.

Parameters (2)
$viewName string
$context array = []

Returns array

phlat/src/Page.php:438
$page->render(array $data = [], ?string $block = null): string

Renders the page view, merging in global and view-specific controller data.

A :block declared {fragment 'name', cache: N} is served from the fragment cache before any controller runs. Such a block must not set response headers - a hit replays only the body.

Parameters (2)
$data array = []
$block ?string = null

Returns string

phlat/src/Page.php:453
$page->cache(): Cache

This page's part of the fragment cache.

Whatever it holds is cleared when the page is saved, moved or deleted, or a page below it is - so a page's cache is only as stale as its subtree.

Returns Cache

phlat/src/Page.php:489

Access

$page->isPublic(): bool

Whether anyone at all may open this page - it and every ancestor published and open to all - whoever is asking.

Returns bool

phlat/src/Page.php:508
$page->isViewable(): bool

Whether the current visitor may open this page.

See assertViewable().

Returns bool

phlat/src/Page.php:518
$page->assertViewable(): void

Throws what the current visitor gets for a page they may not open: a 404 for an unpublished one (it doesn't admit to existing), a login redirect for a gated page when signed out, a 403 when signed in without the role.

The page and every ancestor must pass, and editors and the CLI see everything (App::isEditor()). Registry::scope() applies the same rule to listings.

phlat/src/Page.php:529

Routing

$page->route(): Page

Dispatches the request sub-path against this page's view router.

Returns the page to render (may differ if a route handler returns a different Page).

Returns Page

phlat/src/Page.php:581
$page->remainder(): string

Returns the request path after stripping this page's own URL prefix, trimmed of slashes.

Returns string

phlat/src/Page.php:639
$page->target(): ?Page

Resolves remainder() as a Page, the common case behind most remainder() call sites.

Returns ?Page

phlat/src/Page.php:648
$page->segment(int $n): ?string

Returns the nth segment (1-indexed) of the request sub-path, or null.

Parameters (1)
$n int

Returns ?string

phlat/src/Page.php:655

url

$page->url(string $path = '', array $query = []): string

Returns the site-relative URL by stripping the pages/ root from the filesystem path.

Always starts with /, never ends with / except root which is just /.

Parameters (2)
$path string = ''
$query array = []

Returns string

phlat/src/Page.php:662

Tree

$page->parent(): ?Page

Returns the parent page, or null if this page has no parent (including root pages).

Returns ?Page

phlat/src/Page.php:676
$page->parents(string $query = ''): PageCollection

Returns all ancestor pages from root to immediate parent, lazily computed and cached.

A $query (the find() DSL, e.g. 'view=section') keeps only the ancestors that match.

Parameters (1)
$query string = ''

Returns PageCollection

phlat/src/Page.php:686
$page->closest(string $query): ?Page

Returns the nearest page matching $query (the find() DSL) walking up from this page, this page included, or null if none does.

Parameters (1)
$query string

Returns ?Page

phlat/src/Page.php:699
$page->root(): Page

Returns the root page.

For root pages, returns $this.

Returns Page

phlat/src/Page.php:735
$page->section(): Page

Returns the top-level section page.

For root pages, returns $this.

Returns Page

phlat/src/Page.php:741
$page->depth(): int

Returns the depth in the page tree. 0 for root pages.

Returns int

phlat/src/Page.php:747
$page->childDepth(): int

The depth new children are placed at: one below this page, or deeper when its view's `children.path` puts them in folders.

Returns int

phlat/src/Page.php:753
$page->reorderable(): bool

Whether this page's children are put in order by hand: its view's `children.sort` is `position`.

Returns bool

phlat/src/Page.php:759
$page->childViews(): array

The views an editor may give a new child: the view's `children.views`.

None listed means it takes no children.

Returns array

phlat/src/Page.php:765
$page->siblings(string $query = '', bool $includeHidden = false): PageCollection

Returns sibling pages - children of the parent, excluding this page.

Excludes hidden pages unless $includeHidden is true.

Parameters (2)
$query string = ''
$includeHidden bool = false

Returns PageCollection

phlat/src/Page.php:771
$page->next(string $query = '', bool $includeHidden = false): ?Page

Returns the next sibling in parent's child order, or null if this is the last.

With a $query (the find() DSL), the next one that matches.

Parameters (2)
$query string = ''
$includeHidden bool = false

Returns ?Page

phlat/src/Page.php:781
$page->prev(string $query = '', bool $includeHidden = false): ?Page

Returns the previous sibling in parent's child order, or null if this is the first.

With a $query (the find() DSL), the previous one that matches.

Parameters (2)
$query string = ''
$includeHidden bool = false

Returns ?Page

phlat/src/Page.php:787
$page->contains(Page $other): bool

True if $other is this page or a descendant of it.

Parameters (1)
$other Page

Returns bool

phlat/src/Page.php:816
$page->hasChildren(bool $includeHidden = false): bool

True if this page has any children.

Parameters (1)
$includeHidden bool = false

Returns bool

phlat/src/Page.php:826
$page->isActive(): bool

True if this page is the current request page.

Returns bool

phlat/src/Page.php:832
$page->isOpen(): bool

True if this page is active or contains the active page.

Returns bool

phlat/src/Page.php:838
$page->child(string $name): ?Page

Returns a named child page without checking whether it exists.

Parameters (1)
$name string

Returns ?Page

phlat/src/Page.php:844

has

$page->has(string $slug): bool

Whether a child page folder already exists on disk.

Parameters (1)
$slug string

Returns bool

phlat/src/Page.php:852

Children

new

$page->new(string $name, array $data = []): Page

Creates a new child page: mints its uuid and writes a complete, minimal _index.json in one shot, then applies $data via the normal save() path - structural keys (view/hidden/ published/locked) to _index.json, everything else to _data.json (only written if there's content).

The page is published unless $data says published => false. Where it goes is this page's view's children.path - {year}/{month}/{day}/{slug}, {uuid:2}/{uuid} - and any folder on the way is made as a hidden page of this view. Throws NotFoundException if this page doesn't exist, ForbiddenException if it is locked or not in pages/, and ConflictException if the slug is already taken.

Parameters (2)
$name string
$data array = []

Returns Page

phlat/src/Page.php:869
$page->children(string $query = '', bool $includeHidden = false): PageCollection

Queries the registry for direct child pages, ordered by the view's own `children.sort` (_index.json), unless $query supplies its own sort= to override it.

Excludes hidden pages unless $includeHidden is true or $query supplies its own hidden= condition. Pass a depth= condition in $query to override the direct-children depth - the two will conflict rather than combine.

Parameters (2)
$query string = ''
$includeHidden bool = false

Returns PageCollection

phlat/src/Page.php:944
$page->pageLimit(?int $limit = null): int

The page size: $limit, else the view's `pagination.limit` over the app's. 0 means no limit.

Parameters (1)
$limit ?int = null

Returns int

phlat/src/Page.php:969
$page->paginate(string $query = '', ?int $limit = null): PageCollection

The current `?page=N` slice of children($query); every child when the limit is 0.

Parameters (2)
$query string = ''
$limit ?int = null

Returns PageCollection

phlat/src/Page.php:975
$page->pageCount(string $query = '', ?int $limit = null): int

How many pages children($query) fill at the page limit; 1 when the limit is 0.

Parameters (2)
$query string = ''
$limit ?int = null

Returns int

phlat/src/Page.php:987
$page->find(string $query = ''): PageCollection

Queries the registry for pages within this page's subtree.

Recursive by default - pass a depth= condition in $query (e.g. 'depth=' . ($page->depth() + 1)) to limit to a single level.

Parameters (1)
$query string = ''

Returns PageCollection

phlat/src/Page.php:1006

Files

$page->fileSourcePath(): string

Folder a file() call mirrors source files from.

Overridden by AddonPage, whose files ship in the addon's pages folder even when a real site page backs it.

Returns string

phlat/src/Page.php:1021
$page->publicPath(): string

Returns this page's public-mirror directory, e.g. "" -> public/, "blog/post" -> public/blog/post.

Returns string

phlat/src/Page.php:1027
$page->file(string $uri): PageFile

Resolves a file from this page's own folder.

The only way a file becomes publicly visible.

Parameters (1)
$uri string

Returns PageFile

phlat/src/Page.php:1034
$page->image(string $uri): PageImage

Resolves an image from this page's own folder.

The only way an image becomes publicly visible.

Parameters (1)
$uri string

Returns PageImage

phlat/src/Page.php:1042
$page->files(string $query = ''): array

This page's files, narrowed by the query DSL over filename, name, extension, type, mime, size, modified and their metadata fields: `files('type=image,sort=filename,limit=4')`.

Parameters (1)
$query string = ''

Returns array

phlat/src/Page.php:1050

From Record

$page->assertUnlocked(): void

A locked record is protected: it can't be changed or deleted until `locked` is turned off.

phlat/src/Data/Record.php:288

create

static
Page::create(App $app, string $path, array $data, callable $make, callable $guard, string $uuid = '', ?string $key = null): T

The one way a record comes into being: under the lock for $key (default: the path) $guard refuses a conflict, then $make builds the record at $path and save() applies $data.

Emits {page|user|item}.create:after.

Parameters (7)
$app App
$path string
$data array
$make callable
$guard callable
$uuid string = ''
$key ?string = null

Returns T

phlat/src/Data/Record.php:90
$page->exists(): bool

Whether the record is on disk.

Returns bool

phlat/src/Data/Record.php:204

generateUuid

static
Page::generateUuid(App $app): string

The current system uuid format - the single source of truth for tooling that needs to mint or recognize one.

Parameters (1)
$app App

Returns string

phlat/src/Data/Record.php:76
$page->index(): DataFile

The `_index.json` file: uuid, timestamps and the type's structural keys.

Returns DataFile

phlat/src/Data/Record.php:174
$page->isSiteObject(): bool

Whether it lives in the site rather than in `phlat/` or an addon.

Returns bool

phlat/src/Data/Record.php:168

keyFor

static
Page::keyFor(string $type, string $value): string

Builds a registry uuid key from a type and identity value, e.g. keyFor('page', $uuid) -> "page:{uuid}".

Parameters (2)
$type string
$value string

Returns string

phlat/src/Data/Record.php:156
$page->name(): string

The folder name: the last segment of a page's URL, or a username.

Returns string

phlat/src/Data/Record.php:232
$page->path(): string

The record's folder, with a trailing slash.

Returns string

phlat/src/Data/Record.php:210
$page->publishedData(): DataFile

The canonical _data.json contents, bypassing any draft/preview override (e.g.

Page's autosave-aware data()). Writes and search indexing must always go through this, never the overridable data() accessor, so a draft in progress can never clobber or leak into the persisted record.

Returns DataFile

phlat/src/Data/Record.php:191
$page->registryKey(): string

The registry's uuid key for this object, e.g. "page:{uuid}".

Returns string

phlat/src/Data/Record.php:162
$page->upload(array $file, array $options = []): PageFile

Validates and stores an uploaded file (a raw $_FILES-shape array) into this record's own folder.

Only a page or a user owns files.

Parameters (2)
$file array
$options array = []

Returns PageFile

phlat/src/Data/Record.php:216