Generates .phpstorm.meta.php for ProcessWire API autocompletion in PhpStorm.
- Autocomplete wire container keys for
wire('...')andWire::wire('...') - Autocomplete module names for
Modules::get()andModules::install() - Autocomplete field names for
Fields::get() - Autocomplete template names for
Templates::get() - Autocomplete unique page names for
Pages::get() - Autocomplete hookable methods for
Wire::addHook*() - Autocomplete page status constants/strings for
Page::status(),addStatus(),removeStatus(),hasStatus() - Autocomplete field flags for
Field::addFlag(),removeFlag(),hasFlag() - Autocomplete template cache-expire constants for
Template::cacheExpire() - Autocomplete Inputfield collapsed constants for
Inputfield::collapsed() - Autocomplete sort flags for
WireArray::sort()/sortFlags()/unique()andPageArray::sort()/sortFlags()/unique() - Optional: Field type autocompletion per Page class (when enabled in module config)
- Copy the module folder into
site/modules/ProcessWirePhpStormMeta/. - Install the module in the ProcessWire admin.
- Default path:
site/assets/.phpstorm.meta.php(configurable in module settings). - The file regenerates automatically when fields, templates, or modules change (debounced).
- You can manually regenerate from the module settings screen.
- Optional: enable "Generate page-class field metadata" in module settings for field type hints per Page class. This is intentionally basic. For richer field stubs, use AutoTemplateStubs.
Add custom completions via the generateCustomMetaContent() hook. Multiple hooks concatenate.
This example autocompletes block names for renderBlock() — a custom function that
renders site/templates/blocks/*.php partials:
// $content = renderBlock('hero', $page);
$wire->addHookAfter("ProcessWirePhpStormMeta::generateCustomMetaContent", function($event) {
$names = [];
foreach (glob(wire()->config->paths->templates . "blocks/*.php") ?: [] as $f) {
$names[] = pathinfo($f, PATHINFO_FILENAME);
}
if (empty($names)) return;
$custom = "\n registerArgumentsSet(\"block_names\",\n";
foreach ($names as $n) $custom .= " \"{$n}\",\n";
$custom .= " );\n\n";
$custom .= " expectedArguments(\\ProcessWire\\renderBlock(), 0, argumentsSet(\"block_names\"));\n";
$event->return .= $custom;
});$tracy = $modules->get('TracyDebugger');
// Autocomplete + correct class type for navigation and code insight$page = wire('page');
$pages = $this->wire('pages');
$cache = wire('cache');
// Autocomplete for keys like page/pages/cache/etc.$body = $fields->get('body');
// Autocomplete field names, fewer typos$tpl = $templates->get('basic-page');
// Autocomplete template names$home = $pages->get('/');
// Maps to the page class when page classes are enabled$page->status(Page::statusHidden);
$page->addStatus('draft');
$page->removeStatus(Page::statusUnpublished);
$page->hasStatus('locked');$field->addFlag(Field::flagAutojoin);
$field->removeFlag(Field::flagAccess);
$field->hasFlag(Field::flagGlobal);$template->cacheExpire(Template::cacheExpireParents);$inputfield->collapsed(Inputfield::collapsedYesAjax);$items->sort('title', SORT_NATURAL | SORT_FLAG_CASE);
$items->sortFlags(SORT_NATURAL);
$items->unique(SORT_STRING);$home = $pages->get('/');
// $home is HomePage (page class)
// Field types are inferred from the template fieldgroup
// e.g. $home->hero_image -> Pageimage or Pageimages depending on field settings$wire->addHookAfter('Pages::save', function($event) {
// Autocomplete hookable methods while typing the hook string
});- Hook scanning reads ProcessWire core, modules, admin templates, and page classes to build the hook list.
- If page classes are enabled, page names map to their page class; otherwise they map to
Page. - Improvement suggestions and PRs are welcome.
Mozilla Public License 2.0. See LICENSE.