pw-pages
Use when constructing ProcessWire Selectors or manipulating Page objects — finding, filtering, creating, editing, trashing, and deleting pages.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when constructing ProcessWire Selectors or manipulating Page objects — finding, filtering, creating, editing, trashing, and deleting pages.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
| name | pw-pages |
| description | Use when constructing ProcessWire Selectors or manipulating Page objects — finding, filtering, creating, editing, trashing, and deleting pages. |
| risk | safe |
| source | processwire-boost |
| date_added | 2026-04-08 |
CRITICAL RULE: Before using selectors in API calls, always verify the available API methods by consulting .agents/docs/index.md. Never hallucinate API methods.
Selectors are the foundational querying language in ProcessWire. They are simple strings of text used in $pages->find(), $pages->get(), $page->children(), $page->siblings(), and even for filtering arrays and fields.
A standard selector consists of a field, an operator, and a value.
$pages->find("template=product");
Fields can be combined natively in one string. Commas , act as AND.
$pages->find("template=product, parent=/shop/, get_price>100");
ProcessWire offers a highly flexible set of operators.
= : Equal to!= : Not equal to (or use negation like !body*=word)< / <= : Less than (or equal to)> / >= : Greater than (or equal to)_Note: Using _=, ~=heavily relies on MySQL FULLTEXT indexes (typically 4+ chars required, ignores stop-words). Use%= if you need to match short strings or stop-words.*
*= : Contains exact phrase / text (words must be sequential).~= : Contains all words (order independent).%= : Contains phrase/text LIKE (SQL LIKE equivalent, no length restrictions).^= : Starts with text.$= : Ends with text.~|=: Contains any words.**=: Partial word matching (useful for live searches).You can specify OR logic on fields, values, or entire groups.
OR Values: Pipe | separates possible values.
$pages->find("template=article|news");
OR Fields: Pipe | separates possible fields.
$pages->find("title|summary*=bitcoin");
OR Groups (Parentheses): Specify multiple full conditions where only one group needs to match.
$pages->find("template=product, stock>0, (featured_from<=today, featured_to>=today), (highlighted=1)");
Sorting: Use sort=field. Precede with a minus - for descending order.
$pages->find("template=news, sort=-published_date, sort=title");
(Note: $pages->find() defaults to MySQL text relevance if no sort is provided. Always provide a sort when order matters!)
Limit/Pagination:
$pages->find("template=skyscraper, limit=50"); // Used natively with pagination modules
You can dive deep into complex fields directly from the selector.
Count Selectors: Target pages based on the quantity inside a multi-value field.
$pages->find("images.count>=3");
Subfield Selectors: Query inner properties of complex fields (Page Reference, Repeater, Image, etc).
$pages->find("buildings.feet_high>1000, buildings.year_built<1980");
Matching the exact same row (@):
If the field is a multi-value field (e.g. Repeaters), the standard subfield selector might match feet_high from row A, and year_built from row B. To force the selector to match BOTH properties within the same exact row, use @:
$pages->find("template=house, @categories.name=modern, @categories.featured=1");
Sub-selectors [...] :
A sub-selector runs a query on the related field dynamically.
// Find products whose company has >5 locations, and one location is in Finland
$pages->find("template=product, company=[locations>5, locations.title%=Finland]");
By default, database-querying selectors (find(), children()) exclude hidden, unpublished, or access-restricted pages. $pages->get() is the exception (assumes include=all).
You can override these exclusions:
include=hidden : Allows hidden pages.include=unpublished : Allows both hidden and unpublished.include=all : Overrides all restrictions (hidden, unpublished, access control).check_access=0 : Disables role-based access checks for the query, but still excludes unpublished pages.Always sanitize user input before passing it into a selector.
// Integers:
$year = (int) $input->get->year;
// Arbitrary string values:
$k = $sanitizer->selectorValue($input->get->keyword);
$results = $pages->find("title|body~=$k");
Always use Page instances to insert new content.
$p = new \ProcessWire\Page();
$p->template = "article";
$p->parent = $pages->get("/articles/"); // MUST have a parent
$p->name = $sanitizer->pageName("My New Article!"); // URL slug
$p->title = "My New Article!";
$p->save();
// Alternatively, use the shortcut:
$p = $pages->add("article", "/articles/", "my-new-article", [
'title' => 'My New Article!'
]);
You must call ->of(false) to turn off output formatting before saving a page that has already been loaded from the database, otherwise textformatters might corrupt data.
$p = $pages->get(1234);
$p->of(false); // TURN OFF OUTPUT FORMATTING
$p->title = "Updated Title";
$p->my_custom_field = "New Value";
$p->save();
Use $pages->trash() to move a page to the trash securely. Only use $pages->delete() when absolutely necessary as it skips the trash.
$p = $pages->get(1234);
if ($p->id && $p->trashable()) {
$pages->trash($p);
}
limit= on $pages->find() for large datasets$pages->count($selector) instead of $pages->find($selector)->count() — avoids loading all pages into memoryid, name, template) in selectors$pages->uncacheAll() after processing large batches$page->of(false) before modifying output-formatted pagesUse when building, structuring, or refactoring native backend modules for ProcessWire using PHP 8.4 and strict typing.
Use when designing, structuring, or rendering HTML for ProcessWire Admin interfaces, custom Process modules, or Inputfields.
Use when brainstorming or designing ProcessWire modules, templates, field schemas, or hooks to resolve ambiguity and validate architecture before implementation.
Use when creating, executing, or managing Pest tests within ProcessWire or ProcessWire modules, including Test-Driven Development (TDD) tasks.
Use when encountering any bug, test failure, blank screen of death, or unexpected behavior in ProcessWire before proposing fixes.
Use when creating or updating module documentation, package READMEs, architecture guides, or CLI command references for ProcessWire projects.