Dynamic Content Relationships with ProcessWire Page Reference Selectors
Learn to build dynamic content relationships in ProcessWire using Page Reference fields with Selector strings — enabling flexible cross-referencing without hardcoded IDs, with admin UI that updates automatically as content changes.
19 Aug 2025, 02:06 UTC

Hardcoding page IDs or relying on rigid parent-child hierarchies creates a brittle CMS structure. When content moves or is deleted, these links break. In ProcessWire, the most robust way to manage relationships is by using Page Reference fields combined with Selector strings to create dynamic content pools that update automatically at runtime.
Instead of selecting a static page from a list, you can define a set of rules (a selector) that determines which pages are 'eligible.' This ensures your 'Related Articles' or 'Featured Products' sections always reflect the latest data without manual intervention every time a new post is published.
Prerequisites
- ProcessWire version 2.5 or higher.
- Administrative access to the Template Fields module.
- A defined template with fields you wish to filter (e.g., a 'category' field or 'status').
Configuring Dynamic Page Reference Fields
To implement a dynamic relationship, you must configure the Page Reference field to use a selector string rather than a fixed page tree.
- Navigate to Edit > Templates and select the template where you want the relationship.
- Create or edit a field of type Page Reference (e.g., 'related_articles').
- In the Input tab, ensure 'Multiple values' is checked if you want more than one relationship.
- Locate the Selectable Pages setting. This is where the logic resides.
- Enter a Selector string to filter the available pages shown in the admin interface.
Practical Example: Contextual Related Content
Suppose you have a blog where you want to link to other articles that belong to the same category, excluding archived posts. Instead of picking pages manually, you would use the following selector in the Selectable Pages field:
| Selector String | Description |
|---|---|
template=article, categories=tech, status=1, sort=-created |
Filters for 'article' templates in the 'tech' category that are active (1), sorted by newest. |
has_parent=/news/, limit=5 |
Restricts selection to the /news/ section and caps the list at 5 items. |
Handling the Data on the Frontend
While the field stores only page IDs for database efficiency, the ProcessWire API returns them as page objects. When you iterate through these in your template files, the engine handles the lookup for you automatically.
// In your template file (e.g., article.php)
if($page->related_articles->count) {
echo 'Related Reading:
';
foreach($page->related_articles as $related) {
// We check if the page still exists to avoid errors
if($related->id) {
echo '- '.$related->title.'
';
}
}
echo '
';
}
Diagnostic Checks and Verification
To ensure your dynamic relationships are working correctly, perform the following checks:
- Admin Visibility: Open the page editor for the parent page. Click the selection dropdown. Ensure only pages matching your selector string appear.
- Dynamic Updates: Create a new page that matches the selector criteria. Refresh the page editor; the new page should appear in the selection list without needing to update the field configuration.
- Orphaned References: Delete a page that was previously referenced. On the frontend, use
var_dump($page->related_articles->id)to verify it returns 0 or null, ensuring your code does not crash on missing references.
Limitations and Performance
While selectors are powerful, complex queries on non-indexed fields can slow down admin performance on sites with thousands of pages.
- Indexing: Always use fields like template, parent, created, or status in selectors — these are indexed. Avoid filtering on custom text fields without indexes in high-traffic admin areas.
- Limit Clause: Add
limit=50(or similar) to your selector to cap the admin dropdown size and prevent memory issues. - Permissions: Selector strings evaluate in the context of the current user. If an editor lacks 'view' access to certain pages, those pages won't appear in their dropdown even if they match the selector.
- Stale References: Changing a selector after content exists does not update stored references — only affects future selections. Orphaned IDs remain until manually cleared.
Recovery: Detecting Broken References
If a referenced page is deleted, the field stores the orphaned ID. Use $pages->find('my_ref_field.id=123') to detect broken references across the site. In templates, $page->my_ref_field->id returns 0 for missing pages, allowing safe conditional rendering.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.