Skip to content

Index framework global helpers loaded outside Composer autoload#175

Open
dereuromark wants to merge 1 commit into
PHPantom-dev:mainfrom
dereuromark:index-bootstrap-global-helpers
Open

Index framework global helpers loaded outside Composer autoload#175
dereuromark wants to merge 1 commit into
PHPantom-dev:mainfrom
dereuromark:index-bootstrap-global-helpers

Conversation

@dereuromark

@dereuromark dereuromark commented Jun 27, 2026

Copy link
Copy Markdown

Problem

Global functions defined in vendor/ are reported as unknown_function when their definition file is loaded by the framework's own bootstrap rather than Composer's files autoload.

CakePHP is the canonical case. Its global aliases (__, h, env, pr, debug, collection, ...) live in vendor/cakephp/cakephp/src/*/functions_global.php. Those files are not listed in autoload_files.php. They are pulled in by the app bootstrap:

// config/bootstrap.php
require CAKE . 'functions.php';   // -> src/functions.php, which require's each */functions_global.php

scan_autoload_files only seeds from autoload_files.php (and follows require_once chains out of those), so the *_global.php siblings are never reached. Every __() call - the single most common helper in a Cake template/controller - resolves to "unknown function".

Measured impact

analyze on a real CakePHP 5 application:

total findings unknown_function
before 1332 1002 (968 of them __)
after 346 15

A 74% drop in total findings; the remaining 15 unknown_function are unrelated parse edge cases, not globals.

Fix

For each file already listed in autoload_files.php, also seed any sibling in the same directory whose name ends in _global.php. The existing pipeline then handles the rest: the eager full-parse in preload_autoload_files picks up the function_exists-guarded definitions (depth > 0) that the byte scan skips.

The lookup is anchored to existing autoload entries - one read_dir per unique directory - rather than a blind walk of the vendor tree, so the cost is bounded and proportional to the autoload-files set. Indexing extra global-function files is purely additive (more resolvable symbols), so there is no risk of changing existing resolution.

This is framework-agnostic: any package that ships a <name>_global.php beside an autoloaded helper benefits. CakePHP is just the most prominent example.

Some frameworks ship their global function aliases in a `*_global.php`
file that sits beside an autoloaded `functions.php` but is pulled in by
the application bootstrap rather than Composer's `files` autoload, so it
never appears in `autoload_files.php`. CakePHP is the canonical case:
`src/Core/functions_global.php` defines `__`, `h`, `env`, `pr`, ... and
is loaded via `require CAKE . 'functions.php'` in `config/bootstrap.php`.

The autoload-file scan only followed `autoload_files.php` and their
require_once chains, so these globals were invisible and every `__()`
call reported "unknown function". On a real CakePHP 5 app this was about
1000 of 1330 analyze findings (968 of them just `__`).

Seed the scan with any `*_global.php` sibling of an autoload entry. The
lookup is anchored to existing autoload entries (one read_dir per unique
directory) instead of a blind walk of the vendor tree, and the existing
full-parse pass picks up the function_exists-guarded definitions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant