[PRE-RFC] Runtime modules
| From: | Alex Pătrănescu | Date: | Fri, 26 Jun 2026 13:20:05 +0000 |
| Subject: | [PRE-RFC] Runtime modules | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-131538@lists.php.net to get a copy of this message | ||
Hi internals,
I would like to ask for early feedback on an idea I have been
exploring recently: runtime modules.
I put my initial idea in writing here:
https://news-web.php.net/php.internals/127343
I have recently been playing around with the idea locally.
It seems technically doable, but it touches enough parts of the engine
that I would like to check whether this direction makes sense before
writing a proper RFC.
The problem has been discussed many times over the past few years. I
am now looking at it from real-life package level usage with Composer,
and how to achieve package symbol isolation in a way that would
minimally impact the ecosystem.
The rough idea is to have request-lifetime runtime modules.
A runtime module would be a named internal unit with its own userland
class/function/constant tables.
Code running in a module would define symbols into that module, and
symbol identity for module-owned code would effectively become
(module, symbol_name).
The root context would keep the existing behavior, and conceptually we
can view it as a root/default module.
Root context userland symbols would not automatically be visible to
runtime modules.
A module would see its own symbols, PHP internal/builtin symbols, and
symbols from its direct dependencies. This maps fairly naturally to a
Composer style model where a package depends on PHP and on other
packages, but not implicitly on application/root symbols.
Just to make it clearer, composer related, I see it this way:
- each package would be defined in its own module
- module dependencies would map directly from Composer package dependencies
One possible userland API shape I have been using to experiment with is:
```
module_add_dependency(string $module): void
module_run(string $module, Closure $closure): mixed
```
- module_add_dependency() declares a module dependency for the current module.
- module_run() executes the passed closure in the specified module context.
- All execution contexts have attached to them the module they were
defined for, and any new symbols defined while an execution runs would
have the same module. The exception is module_run(), which overrides
the closure module before running it.
The exact API is not the main point at this stage, but I aim to keep it minimal.
I am more interested in whether the model itself is reasonable.
Technically, the engine would need to track module ownership for
compiled code and symbols, keep per-module symbol tables and direct
dependency lists, and make lookup, type resolution, autoload, and
include_once behavior module aware.
Also, due to the dynamic nature of PHP, objects can be passed to
module code that might not have their class known, but I do not see
this as a blocker.
The design I have been considering also rejects visible shadowing:
unrelated modules may define the same symbol name, but adding a
dependency or declaring a later symbol would fail if it makes two
different symbols with the same name visible from the same context.
I would like feedback on this package oriented runtime module model,
especially whether you see any major technical blockers or design
flaws.
I aim to work on turning this into a complete RFC within the next 6
months, but it might take more. I am far from experienced with
internals details, and I will most probably need guidance and help
with the implementation.
It is not something I want to rush, as this could be an important
addition to the language and we need to get it right.
Thank you,
Alex