> On Oct 6, 2024, at 3:25 AM, Juliette Reinders Folmer > <php-internals_nos...@adviesenzo.nl> wrote: > > On 4-10-2024 13:44, Nicolas Grekas wrote: > > Hi Nicolas, >> # Introduction of the new function: get_declared_enums() >> >> About this proposal, I shared a one-liner in the previous thread that shows >> listing only enums is trivial already. >> IMHO we don't need this function since the engine already provides >> everything one needs if they want to list enums. I won't object either, I'm >> just "-0". > > The upside of a PHP native function would be one of performance. > >> # Deprecation of using class_exists() on enum names >> >> This is a big NO on my side. This will break perfectly fine code for the >> sake of some high level ideas that matter less is practice than ensuring >> stability of the PHP platform. A BC break has to be worth it and this is >> clearly not the case to me. The canonical examples are checks like >> `class_exists($c) || interface_exists($c, false) || trait_exists($c, >> false)`. This is common code to check if a symbol exists in >> current PHP. Yet, with your RFC, all such checks would become broken >> immediately. > > Well, this statement made me curious to see just _how_ common this type of > code is, so I've done a scan of the Packagist top 2000 projects [1]. > > The check you mention is used a total of 36 times in ~20 packages out of 2000 > (includes some duplication, mostly within Symfony, which also contains the > fast majority of the uses of the above mentioned combination). > > The full break down of the scan results [2] are as follows: > > Combination of the following function calls within a set of parentheses > (typically: control structure condition): > 4 out of 4: class_exists() + interface_exists() + trait_exists() + > enum_exists() 3 > 3 out of 4: class_exists() + interface_exists() + trait_exists() > 36 > 2 out of 4: class_exists() + interface_exists() > 131 > 2 out of 4: class_exists() + trait_exists() > 8 > 2 out of 4: class_exists() + enum_exists() > 1 > 2 out of 4: interface_exists() + trait_exists() > 1 > > > Combination of the following function calls within the same function scope > (not necessarily in the same statement, excluding the above): > 4 out of 4: class_exists() + interface_exists() + trait_exists() + > enum_exists() 2 > 3 out of 4: class_exists() + interface_exists() + trait_exists() > 17 > 3 out of 4: class_exists() + interface_exists() + enum_exists() > 3 > 2 out of 4: class_exists() + interface_exists() > 32 > 2 out of 4: class_exists() + enum_exists() > 4 > 2 out of 4: class_exists() + trait_exists() > 2 > > Please note that not all of this code would need updating. > >> BTW, this makes me wonder if we could have a new symbol_exists() function, >> that'd basically do the above checks in one go? Mixing this idea with >> Claude's, the signature could be symbol_exists($class, $filter = -1, >> $autoload = true), where $filter is a bitfield that'd allow listing only >> classes, abstract classes, interfaces, enums, traits at will? >> >> # Change of the return value of get_declared_classes() >> >> This proposal is problematic on two aspects: >> The planned BC break feels needless to me. Its motivation is very moot >> compared to its impact on the PHP community, which will be forced to update >> perfectly fine code. > Again, let's look at the real world impact based on a scan of the Packagist > top 2000. > > In the top 2000 packages, there are only 47 calls to the > `get_declared_classes()` function. These calls are found in 29 packages. > [1][3] > And for the record, there are only 16 calls each to > `get_declared_interfaces()` and `get_declared_traits()`. > > Also note that not all of this code would need updating, only that code which > is also targeting enums. > >> The BC break is planned without any ahead-of-change deprecation notice >> (except doc of course). From a deprecation policy POV, we reject this >> practice in the Symfony community. We don't do "hard BC breaks", or >> "unannounced" ones: we mandate that any BC break is first announced in the >> current major. This ensures the community won't miss the notice, and won't >> discover the BC break when it's very late and thus costly. There is always a >> way to follow that policy, so I'd strongly recommend adopting this practice >> in PHP itself, and in this RFC today. Here, this could be done by either >> keeping the function as is in PHP 9, or just deprecating it (in favor of >> get_declared_symbols()?) > > I hear what you are saying and largely agree with you. The problem is, of > course, that it seems unlikely that we can find a way to throw a deprecation > for this, as PHP would then also throw a deprecation for code which needs no > changes (which only _intends_ to look at classes, not enums). > > In the RFC, we mention an alternative approach [4], building upon the > suggestion by Claude. This alternative approach would allow for deprecations > to be thrown, but would, in my estimation, need a longer lead-time. Something > like: introduce the new function in PHP 8.5, deprecate use of the old > functions in PHP 9.last and remove in PHP 10.0. > > I can imagine combining the alternative approach via get_declared_symbols() > with a new symbol_exists() function like you suggest above (with a similar > slow path to deprecate and remove the old functions). > > On the plus side, the alternative approach makes for much more versatile > functionality. In a number of the cases I looked at, the results from various > get_declared_*() functions are combined before further processing, so having > a `get-declared_symbols()` function would allow for simplifying that code. > The same can be said for the *_exists() functions. > > On the downside, the alternative approach makes for a larger BC break (if > combined with deprecation and eventual removal of the old functions).
Given the argued downsides of the current proposal, would introducing `get_declared_symbols()` + `symbols_exists()` really require deprecating the other functions? It seems adding a `get_current_enums()` and `get_declared_symbols()` + `symbols_exists()` functions would address all the same userland developer needs as the proposed RFC (and more) with the only caveat being `get_current_classes()` remains confusing. To address that one remaining concern why not use add a highly visible recommendation at the top of the `get_current_classes()` docs page informing people to use `get_declared_symbols()` when they need only classes. Is there a reason this approach would not be the best way forward compared to the other options currently being discussed? -Mike P.S. And if it is deemed critically important to get rid of the potential confusion regarding the existing `get_current_classes()` behavior it could be "ultrasoft" deprecated, meaning removed in PHP 11, or just left in forever with a warning (although for the life of me I still do not understand why some people are against leaving a deprecated function in forever, especially for things that are changed for clarity, not because they cause harm by themselves.)