After a quick search, it turns out I've mostly reinvented
https://wiki.php.net/rfc/autofunc which I hadn't remembered.
The `spl_autoload_*()` changes it mentions is what I had in mind

There's been changes to php since then, it's been 7 years,
and this adds thoughts on some implementation details.

It's possible to support function / const autoloading
in a way that keeps existing performance.
Some of the objections at the time no longer apply.

- `SOME_CONSTANT` no longer falls back to the literal string in php 8.
  It throws an Error.
- APC (used by some implementations) is no longer supported.
- Many of the objections were against the available implementations
  based on `function __autoload()`, not the concept of autoloading.

  https://www.mail-archive.com/internals@lists.php.net/msg52307.html
- There wasn't much traction from leads for the concept
  or a Proof of Concept to vote on for that RFC (I think).

What if an ambiguous `function_name()` or const outside the global
namespace would attempt to autoload functions in the global namespace
if it would throw an Error, but not the current namespace?

`function_exists()` or `defined()` would not autoload,
to preserve the behavior/performance of current programs.
Anything with the callable type hint (e.g. `array_map`) would also need to be 
modified,
but I think it already needs to do that for method arrays and 'MyClass::method'.

- Same for global constants
- That should avoid the performance hit - this autoloading would only be 
triggered
  when php would previously throw an Error or warning
  for undefined functions/constants.
- This would also avoid the need to load polyfill files (e.g. mbstring)
  or test framework files when their functions/constants are unused.
- One blocker for other autoload proposals
  seemed to be performance if I understood correctly
  (e.g. attempting to autoload NS\strlen() every time strlen was called).

  https://externals.io/message/54425#54616 and 
https://externals.io/message/54425#54655
  detail this - choosing a different order of checks avoids the performance hit.
- In addition to the RFC, changing the signatures to `defined(string $name, 
bool $autoload = false)`
  and `function_exists($name, bool $autoload = false)`
  might be useful ways to allow users to choose to autoload when checking for 
existence.

And there'd have to be a hash map, flag, or other check
to avoid recursion on the same constant/function.

Background: A function call or constant usage is
ambiguous if it could look for the function in two namespaces,
as described by the rules documented in the below link.
It's unambiguous if it ends up looking in only one namespace.

https://www.php.net/manual/en/language.namespaces.rules.php
The only type of ambiguous function call or global constant use is (7.):

> 7. For unqualified names,
>    if no import rule applies and the name refers to a function or constant
>    and the code is outside the global namespace, the name is resolved at 
> runtime.
>    Assuming the code is in namespace A\B, here is how a call to function 
> foo() is resolved:
>    1. It looks for a function from the current namespace: A\B\foo().
>    2. It tries to find and call the global function foo().

My approach should be in line with the current name resolution
for unqualified names outside the global namespace.

1. It (first) looks for a function from the current namespace: A\B\foo().
2. It (next) tries to find and call the global function foo().
3. (Optional) NEW ADDITION: Next, if both functions were undefined,
   the autoloader(s) attempt to autoload the function A\B\foo()
   (and call it instead of throwing if found) before proceeding to step (4.)
4. NEW ADDITION: If both functions were undefined,
   the autoloader(s) attempt to autoload the global function foo()
   (and call it instead of throwing if found) before throwing an Error

And for unambiguous calls, find and autoload the only name it has.

The fact that one of the two possible functions gets cached by the php VM
in CACHED_PTR
(for the lifetime of the request) the first time the function is found
in either namespace will remain unchanged with this proposal.

(Out of scope of the "use global functions/consts" RFC,
so I'm splitting out this discussion. There is no proof of concept yet.)

------

Pros:
- Don't need to preload entire files and dependencies up-front whether or not 
they're used (e.g. with composer),
  to supply functional libraries or frameworks, or to supply polyfills for 
native modules.
- Supporting this encourages using functions/global constants from namespaces,
  where they were previously discouraged by lack of autoloading support,
  or needed manual require_once statements.
- Preloading support makes it easier to avoid \NS\FooDoer::foo() instead of 
\NS\do_foo() in cases which would be unnatural (e.g. classes with just one 
method)
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to