> Am 27.05.2026 um 15:19 schrieb Ben Ramsey <[email protected]>:
>
> On 5/27/26 07:12, [email protected] wrote:
>> Hi internals,
>> I intend to submit an RFC introducing a new file extension for pure-code PHP
>> source files (no leading <?php required) and would like to gather feedback
>> before drafting.
>> Proposal in brief:
>> Files ending in .phpc would be parsed starting in ST_IN_SCRIPTING state. No
>> <?
>> php or ?> tags permitted inside such files. Existing .php files and their
>> semantics are completely unchanged. This is purely additive and BC-clean.
>> Motivation:
>> PHP's mixed-mode default reflects its 1995 templating origins. Since PHP 7+,
>> the
>> language has evolved into a credible general-purpose tool: strict types,
>> enums,
>> readonly classes, property hooks, JIT compilation. I personally maintain
>> PHPolygon, a CPU-bound 3D engine written in PHP – a use case where the
>> templating heritage is pure ceremony. Other modern uses (CLI tooling, queue
>> workers, code generators) share this pattern. A dedicated pure-code file
>> format
>> would be a small but meaningful acknowledgment that PHP-as-language is now a
>> first-class use case alongside PHP-as-template.
>> Prior art and what's different:
>> I have read both rfc/source_files_without_opening_tag (Boutell, 2012,
>> abandoned
>> by author) and rfc/nophptags (Ohgaki, 2014, inactive). My proposal
>> deliberately
>> avoids what I believe were the two design choices that killed them:
>> - No new include syntax (Boutell's AS keyword). Extension-based detection
>> only.
>> - No php.ini-based mode switch (Ohgaki's template_mode). No global config
>> side
>> effects.
>> - No security framing. The mode-switch overhead is parse-time only and
>> OPcache/
>> JIT eliminate it in practice; this proposal is about conceptual clarity and
>> tooling, not performance or LFI mitigation.
>> Implementation:
>> I will write and maintain the implementation patch. Initial scope: extension
>> registration in zend_compile_file, lexer state initialization, OPcache
>> awareness, CLI support, and rejection of <?php/?> tokens inside .phpc files.
>> I
>> will also coordinate with Composer maintainers ahead of RFC submission to
>> confirm autoload support.
>> Open questions for the list:
>> 1. Is the .phpc extension acceptable as the disambiguator, or is there
>> appetite
>> for something else (e.g. shebang line, declare directive – both of which I
>> think
>> are worse, but I'd hear the case)?
>> 2. Should #! shebang lines and UTF-8 BOM be permitted before the implicit
>> scripting state begins? My intent is yes for both.
>> 3. Should __halt_compiler() retain its current behavior in .phpc files? My
>> intent is yes.
>> I welcome substantive critique. If the concept itself is unwanted, I would
>> rather know now than discover it during a vote.
>> Thanks.
>> Hendrik Mennen
>> Maintainer, PHPolygon
>
>
> The problem with assigning meaning to a file extension is that the
> interpreter (currently) doesn't care what the file extension is. As long as
> it's text, it'll process any file and execute what comes after any <?php tags.
>
> What you want is something like this:
>
> php -r "$(cat foo.phpc)"
>
> Of course, this only works for a single file, and the engine won't execute
> code in any included files unless they contain PHP open tags, so the file
> needs a way to tell the engine to parse and execute it as PHP source.
>
> At the risk of bike-shedding, I think it could be easy for others to confuse
> .phpc files as byte-code files, since it's common to see Python byte-code
> files with the .pyc extension. Also, a lot of folks in the community use
> "phpc" as a shorthand and tag to mean "PHP community," though I'm not sure
> this is reason enough not to use the .phpc extension. I don't have any better
> alternative recommendations at this time, though.
>
> Cheers,
> Ben
One more Try for readability:
Hi Ben,
Thanks for the quick response.
> The problem with assigning meaning to a file extension is that the
> interpreter (currently) doesn't care what the file extension is. As long
> as it's text, it'll process any file and execute what comes after any
> <?php tags.
Right, that is the current behavior, and changing it is exactly what the
proposal is about. The engine would learn to check the file extension at the
entry point (zend_compile_file for SAPI/CLI, and the include/require family for
nested loads) and use that to set the initial lexer state. The .php behavior
remains untouched.
That said, you point indirectly at something I do need to address: there are
entry paths where the engine does not have a filename, or has one it should not
trust. Off the top of my head:
- stdin (cat foo.phpc | php). No filename available. Options: require an
explicit CLI flag (php --pure), or simply not support this path and document it.
- eval(). Operates on strings, not files. Extension is irrelevant here; eval()
continues to require <?php as today.
- Phar archives. Internal entries have filenames, so dispatch by extension
should work, but I would need to verify.
- include of a URL stream (rare, often disabled). Same question. Probably
handled by extension on the URL path.
I will work these out explicitly in the RFC draft. Thanks for surfacing it.
> At the risk of bike-shedding, I think it could be easy for others to
> confuse .phpc files as byte-code files, since it's common to see Python
> byte-code files with the .pyc extension.
Fair point, and one I had not weighed heavily enough. The Python .pyc parallel
is real and would cause exactly the kind of one-time confusion that adds
friction to adoption. Boutell's 2012 RFC used .phpp (Pure PHP) for the same
purpose, which avoids the bytecode association. I am open to .phpp or other
suggestions; the disambiguator matters less than the mechanism.
> Also, a lot of folks in the community use "phpc" as a shorthand and tag
> to mean "PHP community," though I'm not sure this is reason enough not
> to use the .phpc extension.
Noted. Less critical than the .pyc concern in my view, but it does reinforce
that .phpc is not the obviously-best choice. I will list candidate extensions
in the RFC and explicitly invite the list to pick one rather than defending a
specific letter.
Thanks again for the substantive feedback.
Hendrik Mennen
Maintainer, PHPolygon