Hi Mike,


There is one problem I can see with this approach though: since PHP 7.4, the 
return value of `get_declared_classes()` (and friends) does not guarantee any 
particular order anymore [2].
So, an `array_slice($symbols, $n)` may not get you the _latest_ classes loaded, 
so I think this would only work if the order of classes is guaranteed in some 
way.
That is a super relevant insight and one I was actually not aware of.

Do you happen to know if it was triggered by an explicit RFC to that effect, or 
if it resulted because of a side-effect of some other implementation change?
I honestly don't know, but if I look through the PHP 7.4 RFC list, I have a niggling suspicion it may have something to do with the Preloading RFC [1] ? I may very well be wrong though.

 From my perspective, that is definitely a BC break and one that I am surprised I never 
noticed before?  Do you also know if it is a case of "not guaranteed, but in-fact 
actual fact it always works that way, or not?"

Well, for the autoloader I previously linked to [2], it was a problematic change which we did have to work around, see [3] and [4] for details of the issues we saw (parent class vs child class order reversals, issues when multiple classes were declared in one file).

I haven't deep-dived into the order change, other than to validate the reported issues and proposed fixes.

What if instead PHP were to implement an optional 2nd callback parameter to 
`include()` / `require()` / `include_once()` / `require_once()` to allow us to 
capture the symbols loaded and their paths? The callback function could return 
`void` and accept an array of `$symbols` with the following guaranteed minimum 
structure?

$symbols = array(
    'classes' => [],
    'interfaces' => [],
    'traits' => [],
    'enums' => [],
);

Except `include()` and friends aren't function calls, but language constructs/expressions and don't take parameters as such, so I don't see how that would be possible without changing `include()` and friends to function calls (along the lines of what happened for `exit` in PHP 8.4 with non-parenthesized use still possible to mitigate the otherwise huge breaking change), or alternatively, introducing wrapper functions for the language constructs - so no change to the existing functionality, but new functions with a signature along the lines of `include_and_get_symbols( $path ): array` with the return value being the symbols loaded from $path.

This approach would be a less disruptive than my prior suggestion

Not so sure about that considering the above ;-)
What do you think if this alternate approach?

This probably needs some more bike shedding ;-)

Smile,
Juliette


1: https://wiki.php.net/rfc/preload
2: https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/6fbbc1078094d905f0773421f13830744a144d1e/autoload.php#L153-L247
3: https://github.com/squizlabs/PHP_CodeSniffer/pull/3130
4: https://github.com/squizlabs/PHP_CodeSniffer/issues/3145

Reply via email to