Skip to content

fix(polyfill): bind the Compat surface eagerly at bootstrap#1

Merged
saifulferoz merged 1 commit into
mainfrom
fix/eager-alias-typed-params
Jul 15, 2026
Merged

fix(polyfill): bind the Compat surface eagerly at bootstrap#1
saifulferoz merged 1 commit into
mainfrom
fix/eager-alias-typed-params

Conversation

@saifulferoz

Copy link
Copy Markdown
Owner

Lazy aliasing left two holes the autoloader cannot close:

  1. PHP never autoloads for parameter/return/instanceof checks. A Compat object passed to consumer code type-hinted with the PhpOffice name (e.g. function f(Worksheet $ws)) threw "TypeError: ... must be of type PhpOffice...\Worksheet, EasyExcel\Compat\Worksheet\Worksheet given" unless something had happened to reference the class name first.

  2. composer prepends its own autoloader, so a polyfill bootstrap loaded before vendor/autoload.php silently lost the PhpOffice* namespace to a co-installed real phpoffice/phpspreadsheet.

eagerAliasCompat() now class_aliases every implemented name at bootstrap (~60 classes, ~12 ms cold, one-time per process), enumerated by scanning the Compat tree (not .compat-surface.json, which tracks the full upstream surface including unimplemented classes). The prepended autoloader stays as the strict-mode tripwire for unimplemented classes. Already-defined names are skipped; EASY_EXCEL_EAGER=0 restores lazy-only aliasing.

Found migrating a report pipeline whose SheetContext constructor type-hints Worksheet: creating the context fataled under strict mode.

Lazy aliasing left two holes the autoloader cannot close:

1. PHP never autoloads for parameter/return/instanceof checks. A Compat
   object passed to consumer code type-hinted with the PhpOffice name
   (e.g. `function f(Worksheet $ws)`) threw
   "TypeError: ... must be of type PhpOffice\...\Worksheet,
   EasyExcel\Compat\Worksheet\Worksheet given" unless something had
   happened to reference the class name first.

2. composer prepends its own autoloader, so a polyfill bootstrap loaded
   before vendor/autoload.php silently lost the PhpOffice\* namespace to
   a co-installed real phpoffice/phpspreadsheet.

eagerAliasCompat() now class_aliases every implemented name at bootstrap
(~60 classes, ~12 ms cold, one-time per process), enumerated by scanning
the Compat tree (not .compat-surface.json, which tracks the full upstream
surface including unimplemented classes). The prepended autoloader stays
as the strict-mode tripwire for unimplemented classes. Already-defined
names are skipped; EASY_EXCEL_EAGER=0 restores lazy-only aliasing.

Found migrating a report pipeline whose SheetContext constructor
type-hints Worksheet: creating the context fataled under strict mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@saifulferoz
saifulferoz merged commit 1bf64f5 into main Jul 15, 2026
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