FieldtypePage

Stores references to one or more ProcessWire pages.

Value type

PageArray by default (when derefAsPage=0), or Page/NullPage/false for single-page mode. Unpublished pages are excluded from the value unless allowUnpub=1 is set on the field.

The value type depends on the derefAsPage field setting:

derefAsPage constantValue when populatedValue when empty
FieldtypePage::derefAsPageArray (0, default)PageArrayempty PageArray
FieldtypePage::derefAsPageOrNullPage (2)PageNullPage
FieldtypePage::derefAsPageOrFalse (1)Pagefalse
Getting and setting values
// --- PageArray mode (derefAsPage=0, default) ---

// Get
$items = $page->page_field;         // PageArray (possibly empty)
$first = $page->page_field->first(); // first Page or boolean false if empty

// Iterate
foreach($page->page_field as $item) {
    echo $item->title;
}

// Set (replaces entire value)
$page->page_field = $pages->find('template=product');
$page->save('page_field');

// Add a page
$page->page_field->add($pages->get(1234));
$page->page_field->add(1234); // same as above
$page->save('page_field');

// Add multiple pages at once
$items = $pages->find('sort=-modified, limit=3');
$page->page_field->add($items);
$page->save('page_field');

// Remove a page
$page->page_field->remove($pages->get(1234));
$page->save('page_field');

// Remove page(s) with selector
$page->page_field->remove('name=foo');

// Remove multiple pages
$items = $page->page_field->find('status>=' . Page::statusHidden);
$page->page_field->remove($items);


// --- Single-page mode (derefAsPage=1 or 2) ---

// Get
$item = $page->page_field;         // Page, NullPage (or false) when empty
if($page->page_field) { ... }      // check if a page was selected when derefAsPage=1
if($page->page_field->id) { ... }  // check if a page was selected when derefAsPage=2

// Set
$page->page_field = $pages->get(1234);  // Page object
$page->page_field = 1234;               // page ID
$page->page_field = '/path/to/page/';   // page path
$page->page_field = null;               // clear
$page->save('page_field');
Selectors

Page reference fields support matching by page ID, page name, page path, count, and subfields of the referenced pages (both native page properties and custom fields):

// Match by page ID
$pages->find('page_field=1234');
$pages->find('page_field=1234|5678');  // either page

// Match by page name
$pages->find('page_field=some-page-name');

// Match by page path
$pages->find('page_field=/path/to/page/');

// Empty / not empty
$pages->find('page_field=""');    // no page selected
$pages->find('page_field!=""');   // at least one page selected

// Count of referenced pages
$pages->find('page_field.count>0');   // has at least one
$pages->find('page_field.count=3');   // exactly 3

// Native page property subfields
$pages->find('page_field.template=product');
$pages->find('page_field.parent=/products/');
$pages->find('page_field.name=some-name');
$pages->find('page_field.status=published');
$pages->find('page_field.created>2026-01-01');

// Custom field subfields (matches pages whose referenced pages have matching custom fields)
$pages->find('page_field.price>100');
$pages->find('page_field.color=red');
$pages->find('page_field.title~=keyword');

Note on subfield matching: When using a custom field subfield (e.g. page_field.price>100), ProcessWire performs a nested $pages->find() internally to resolve which referenced pages match, then checks which pages on the current template reference them. This is powerful but can be slower on large datasets.

Output / markup
// PageArray mode (derefAsPage=0) — iterate or use WireArray methods:
foreach($page->page_field as $item) {
    echo "<a href='$item->url'>$item->title</a>";
}

// Same output as above with alternate syntax
echo $page->page_field->each("<a href='{url}'>{title}</a>");

// Render titles as comma-separated list:
echo $page->page_field->implode(', ', 'title');

// Single-page mode (derefAsPage=1):
if($page->page_field) {
    echo $page->page_field->title;
    echo "<a href='{$page->page_field->url}'>{$page->page_field->title}</a>";
}

// Single-page mode (derefAsPage=2):
if($page->page_field->id) {
    echo $page->page_field->title;
    echo "<a href='{$page->page_field->url}'>{$page->page_field->title}</a>";
}

// String cast to check if value present, works in multi-page mode and both single modes
if("$page->page_field") {
  // value is populated
} else {
  // value is empty
}

// Page fields can be used in selectors
$pages->find("categories=$page->page_field"); 
Creating a page field programmatically
/** @var PageField $field */
$field = $fields->new('page', 'related_products', 'Related Products');

// Restrict selectable pages to a single template
$field->setTemplate('product');

// Or restrict to multiple templates
$field->setTemplates(['product', 'service']);

// Restrict selectable pages to children of a specific parent
$field->setParent('/products/');

// Set the Inputfield type used in the page editor
$field->setInputfield('checkboxes');   // InputfieldCheckboxes
$field->setInputfield('select');       // InputfieldSelect
$field->setInputfield('asmSelect');    // InputfieldAsmSelect (default for multi)

// Return single page rather than PageArray
$field->set('derefAsPage', FieldtypePage::derefAsPageOrNullPage);

$fields->save($field);

// Add the field to a template
$template = $templates->get('your-template');
$template->fieldgroup->add($field);
$template->fieldgroup->save();
Notes
  • derefAsPage setting controls whether the value is a PageArray (0), single Page/false (1), or single Page/NullPage (2). Default is PageArray (0).
  • allowUnpub=1 allows unpublished pages to be included in the value.
  • template_id / template_ids: restrict selectable pages to specific template(s).
  • parent_id: restrict selectable pages to children of a specific parent page.
  • findPagesSelector: custom selector string for finding selectable pages.
  • labelFieldName: the field used as the label in the input (default is title).
  • labelFieldFormat: a $page->getMarkup() format string to use instead of labelFieldName.
  • addable=1: allows editors to create new pages inline from the field input.
  • Circular page references (a page referencing itself) are automatically prevented.
  • Compatible fieldtypes: FieldtypePage and classes extending it only.
  • Database column: int NOT NULL per row, multi-value table (one row per referenced page).
API reference: methods, hooks

Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the FieldtypePage class also inherits all the methods and properties of: FieldtypeMulti, Fieldtype, WireData and Wire.

Show class?     Show args?       Only hookable?    

Common

NameReturnSummary 
FieldtypePage::cleanOrphanedReferences()
None

Find and clean orphaned references in each of FieldtypePage's tables

 
FieldtypePage::exportConfigData(Field $field, array $data)
array

Export configuration values for external consumption

FieldtypePage::exportValue(Page $page, Field $field, $value)
array string

Export value

FieldtypePage::findReferences(Page $page)
PageArray array int

Return pages referencing the given $page, optionally indexed by field name

 
FieldtypePage::formatValue(Page $page, Field $field, $value)
string

Format the given value for output.

FieldtypePage::getBlankValue(Page $page, Field $field)
Page PageArray bool

Return either a blank Page or a blank PageArray or boolean false (depending on derefAsPage setting)

 
FieldtypePage::getCompatibleFieldtypes(Field $field)
Fieldtypes

FieldtypePage instances are only compatible with other FieldtypePage derived classes.

FieldtypePage::getConfigInputfields(Field $field)
InputfieldWrapper

Return configuration fields definable for each FieldtypePage

FieldtypePage::getDatabaseSchema(Field $field)
array

Return the database schema in predefined format

 
FieldtypePage::getFieldClass()
string

Get class name to use Field objects of this type (must be class that extends Field class)

 
FieldtypePage::getFieldSetups()
array

Get setup options and setup functions for new fields

FieldtypePage::getInputfield(Page $page, Field $field)
InputfieldPage

Return an InputfieldPage of the type configured

 
FieldtypePage::getLoadQueryAutojoin(Field $field, DatabaseQuerySelect $query)
DatabaseQuerySelect null

Return the query used for Autojoining this field

 
FieldtypePage::getMatchQuery($query, string $table, string $subfield, string $operator, string $value)
DatabaseQuery

Update a DatabaseQuerySelect object to match a Page

 
FieldtypePage::getSelectorInfo(Field $field)
array

Return array with information about what properties and operators can be used with this field

FieldtypePage::importConfigData(Field $field, array $data)
array

Convert an array of exported data to a format that will be understood internally

FieldtypePage::importValue(Page $page, Field $field, $value)
PageArray

Import value

FieldtypePage::isEmptyValue(Field $field, $value)
bool

Return whether the given value is considered empty or not.

 
FieldtypePage::isValidPage(Page $value, Field $field, Page $forPage)
bool

Validate that that $value is a valid Page for this field

 
FieldtypePage::markupValue(Page $page, Field $field)
MarkupFieldtype string

Render markup value for field

FieldtypePage::sanitizeValue(Page $page, Field $field, $value)
Page PageArray bool

Given a value of unknown type, return a Page or PageArray (depending on $field->derefAsPage setting)

 
FieldtypePage::savePageField(Page $page, Field $field)
bool

Per the Fieldtype interface, Save the given Field from the given Page to the database

FieldtypePage::sleepValue(Page $page, Field $field, $value)
array

Given an 'awake' value, as set by wakeupValue, convert the value back to a basic type for storage in DB.

FieldtypePage::wakeupValue(Page $page, Field $field, $value)
PageArray

Given a raw value (value as stored in DB), return the value as it would appear in a Page object

Additional methods and properties

In addition to the methods and properties above, FieldtypePage also inherits the methods and properties of these classes:

API reference based on ProcessWire core version 3.0.261