Re: [RFC] Pure-code source files via the .phpc extension

From: Date: Tue, 16 Jun 2026 09:58:13 +0000
Subject: Re: [RFC] Pure-code source files via the .phpc extension
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-131319@lists.php.net to get a copy of this message
Le 16/06/2026 à 07:00, Hendrik Mennen a écrit :
Strictly additive Sure thing, but it's not allowing any kind of BC, since including ".phpc" files from older PHP versions would be possible, and would be rendered as text instead of being compiled...
 - A library shipping .phpc files declares the target version    in composer.json:
     "require": { "php": ">=8.6" }
 - composer install fails at install time with a clear    PHP-version error on lower versions. The .phpc file never    reaches a running interpreter that doesn't understand it.  - Library authors who want to support older PHP versions    don't ship .phpc files. Same constraint as readonly    classes, property hooks, enums, etc.  - For non-Composer distribution (manual clone, raw .zip),    the user is on their own - same as for any 8.x feature. For application code (where the deployed PHP version is known) the FC constraint is moot. For shared libraries it is real and worth flagging in the RFC. I will add a Forward Compatibility subsection covering this.
This list is a big reason to not implement your proposal: since it breaks BC for everyone upgrading to the newer PHP version, it's putting a huge burden to the entire ecosystem just to avoid disclosing PHP code as text instead of parsing/compiling it. (and side-note: it also forces potential users of ".phpc" extension to change their code, though I doubt anyone is using this extension, and checking Github isn't enough for that, considering the millions of worldwide projects using PHP). All that makes the RFC absolutely non-additive: you do not /add/ a feature to the language, you are /changing/ how it behaves internally, from not caring about file ext to making a big opinionated choice on one particular extension name.
Reduced ceremony / First-class CLI scripts / Clearer file-mode intent
These largely overlap with Kamil's earlier points; I'd rather not re-litigate the same arguments inline. The Motivation section is being rewritten this week to drop the four-bullet framing entirely in favour of one honest sentence ("modern PHP is overwhelmingly pure-code; <?php is a vestige for those files; .phpc is the smallest mechanism to remove it opt-in") plus a "what this RFC does NOT claim" subsection. If after that you still see no value, that is a fair (3).
I don't think adding a file extension constraint adds any value to PHP. Any file using "<?php" is just five characters at the beginning and all works. Implementing this RFC would imply too much change on the language and the ecosystem, just to avoid writing these five characters. That's way too overkill.
Closing-tag-echo issue, having "?>" somewhere...
To clarify: this RFC does NOT try to solve that. ?> behaviour inside a .phpc file is byte-for-byte identical to .php - drop- out to inline mode is preserved, __halt_compiler() works, <?= has no special meaning. The "What is unchanged" subsection of the RFC says this; I will make it more prominent.
Noted
All existing ecosystem would have to adapt: Composer, IDEs, web servers...
Concede partially. Adoption work is non-zero. The RFC's position:  - Composer: PSR-4 autoloader already accepts a per-rule    extension list; adding .phpc is documentation + a small    Composer-side acknowledgement. RFC commits to opening    that PR pre-landing.  - IDEs / static analysers: configure file modes by extension    via their per-project config; one-line change per tool.    RFC commits to opening tracking issues on day of vote    acceptance.  - Web servers: explicit handler mapping or deny. Appendix A    of the RFC ships canonical snippets for Apache, Nginx,    Caddy, FrankenPHP. You are right that adoption would be slow. I do not think that disqualifies an additive opt-in feature, but I respect that you do.
It's not about respecting what I do, or making the adoption quick, it's about the relevance and impact of it. Your RFC enforces a change in all the three elements on this list: package managers, IDEs and web servers. I think you already know that 80% of worldwide websites and apps are using PHP. You can *not* expect some hosting providers to advertise support for a new PHP version if that version implies that they must update their entire HTTP configuration on all their servers, VMs and so on, even if it's a "one-liner" in your mind. I've been there on a small scale, updating one machine that served dozens of domain names, and trust me, it comes with a cost, and I'm a really smaller-cases user. Now scale this to the worldwide web. It's just not rational at all. This RFC not only enforces a "config change", it enforces lots of companies to actually PAY for forward-compatibility before even upgrading PHP. In almost all its time, PHP's strength have been its ease to deploy and configure, and here you're making deployment and configuration more complex for the sake of removing five characters at the beginning of a file. That's just too much.
Templating system based on PHP files [...] many such projects
Agreed, and .phpc proposes to harm none of them. It is opt-in by filename. Template engines (compiled .php cache files prefixed with <?php) are untouched; hand-written .phtml templates are untouched; a legacy codebase that never adopts .phpc loses nothing.
On the template part, /maybe/ a legacy codebase loses nothing. Maybe. But all other arguments still stand.
Definition files (that I suggested in another internals thread) [...] but even having "?>" from inside a function is no issue
I have not read your Definition files thread yet; pointer welcome. If that concept subsumes .phpc as a special case of something broader, I would rather refine the bigger idea than ship a smaller one that conflicts with it. Genuinely interested.
You can read the thread there: https://externals.io/message/131171 It's on the internals mailing-list, feel free to check it out.

« previous php.internals (#131319) next »