8.1 Enum Polyfill
marc-mabe opened this issue · comments
Hi,
I have created a proof of concept to emulate enumerations for PHP < 8.1.
The code still WIP but the basics are working already - see https://github.com/marc-mabe/php-enum-polyfill
This way it's possible to write compatible code by still being able to take advantages of native enumeration support.
The main disadvantages are:
- You have to use a magic function call to access enum cases
MyEnum::MY_CASE()
instead ofMyEnum::MY_CASE
- You have to manage your enumerations two times (polyfill version + native version)
- Your native enumerations need to include a trait as BC layer
Would you consider to add something like this to symfony/polyfill project?
The fact that you have to write different code means that it is not actually a polyfill. So this is out of scope of this repo.
The goal of the polyfills is that you write your code the modern way.
Hi @stof,
Thanks for your fast reply.
I totally understand your concerns and also agree with you.
I still think that such "polyfill" or however it could be named has a lot of value in itself so I'll work on making it an own package.
I come an issue with your current polyfill version for 8.1 for enum_exists
https://github.com/symfony/polyfill/blob/main/src/Php81/bootstrap.php#L23 . This would prevent users from using your library as well the enum library together.
Should I open another issue for that or do you know how I could force my version to be loaded before your version?
@marc-mabe making your own fake enum that must not be used like an actual PHP 8.1 enum report true
in enum_exists
looks wrong to me. Code using enum_exists
would assume that such enums are used in the standard way.
@stof I would like to keep the differences as small as possible to make it as simple as possible for users to work with it as normal and also to remove it later on PHP < 8.1 is not a thing anymore.
Currently I'm testing for instanceof UnitEnum
but I want to change that to an own unique class instanceof UnitEnumPolyfill
to make sure it returns true for a known emulated enum only and not for anything else imlementing this interface for whatever reason.
The point here is that if someone uses enum_class
it has only any value if enums are supported - that means if the code is either running on 8.1 or it's using the emulated version. I can't come up with a valid use case elsewhere.
@marc-mabe but my whole point is that your enum library does not expose the actual enum API (which cannot be polyfilled). As the usage cannot be the same, making enum_exists
would break things. If a library does a enum_exists
and then use the enum API based on that, it would be incompatible with your fake enums if that method return true while a different way to use them is necessary.
As your library exposes a different enum API, it should also expose a different existence function rather than reusing the PHP 8.1 name.
If a library does a enum_exists and then use the enum API based on that
How can a library using enum_exists
running on < 8.1 ? and for what value ?
If it's running on >= 8.1 the native function is used.
@marc-mabe but that's the whole point of a polyfill: the library could support both PHP 8 and PHP 8.1 with the same codebase. And that's why our polyfill for enum_exists
returns false
all the time, because no enum (compatible with the way they are used in newer PHP versions) will ever exists in 8.0 or older.
I'm closing the issue as explained by @stof. The point of polyfill is to expose an API 100% compatible. So that application or library can use the exact same code when running on the platform using PHP 8.1 or running with the polyfill version.
How can a library using enum_exists running on < 8.1 ? and for what value ?
Hypothetical situation: VendorB provide code compatible with PHP 8.0 and PHP 8.1
VendorA deprecated code compatible with PHP8.0 in favor of new version with enum
namespace VendorA
{
enum Worflow
{
case PUBLISH
}
/**
* @deprecated use Workflow instead
*/
class WorflowEvents
{
public const PUBLISH = 'publish';
}
}
namespace VendorB
{
use VendorA\Workflow;
use VendorA\WorflowEvents;
if (enum_exists(Worflow::class)) {
$this->workflow->apply(Worflow::PUBLISH);
} else {
$this->workflow->apply(WorflowEvents::PUBLISH);
}
}
This kind of code would work with polyfilled version of enum_exists
running on PHP <8.1.
For anyone who is interested I have finished the first working version now here https://github.com/marc-mabe/php-enum-cl with the following changes by result of the discussion of this thread:
- Don't name it polyfill but instead compatibility layer or emulated
- Include an own version of
enum_exists
but on a different namespace to make sure it's being used in the correct context only
Thanks for your input 👍