dagfinn | 11 May, 2008 00:04
I'm currently working about equally in PHP and Java. I can't say I've fallen in love with Java. But Java does have a feature or two that would be useful in PHP. One of them is the Enum (enumeration, that is), which is traditional in some languages and DBMSes (including MySQL) and was introduced in Java 1.5 (or is that 5.0? I'm sure they do that just to expose people like me as Java amateurs).
Enumerations are useful when a variable can have one of a given number of values. Actually useful examples I've encountered in web programming are states or stages in a process and user roles. Another kind of example is one I used in PHP In Action: an authorization system with three fixed roles or categories of user: regular, webmaster and administrator.
If we represent the roles as text strings, we risk getting our tests wrong:if ($role == 'amdinistrator')...
The only problem is that the word “administrator” is misspelled, so the test won't work.
This can be solve by representing the values with named constanst instead. Using class constants in PHP 5:class Role const REGULAR = 1; const WEBMASTER = 2; const ADMINISTRATOR = 3; ...
Now we can do this instead:
We won't get away with any misspellings here; using an undefined class constant is a fatal error. Compared to global constants, this may be easier to figure out, not least because we know where the constant is defined (inside the Role class) just by looking at it.
This is called the int Enum pattern in the official description of Java Enums. The documentation also lists some problems with this, starting with type safety, which we're not that concerned with in PHP anyway. A more relevant problem is the fact that when you print the value, you just get the number.
But I don't see why you shouldn't use strings for the values:class Role const REGULAR = 'REGULAR'; const WEBMASTER = 'WEBMASTER'; const ADMINISTRATOR = 'ADMINISTRATOR'; ...
One PHP-specific problem I didn't mention in the book is the problem that happens with long class names. Since we still don't officially have namespaces in PHP, we will easily end up with nauseatingly long constant names, like this:
It's quite depressing to have to do that a lot. I've tried putting constants in their own class with a shorter name, but I didn't like it much. One thing I tried recently was creating instance methods to return the constant value:
class MyProject_Authorization_RBAC_Role... public function REGULAR { return self::REGULAR } public function WEBMASTER { return self::WEBMASTER } public function ADMINISTRATOR { return self::ADMINISTRATOR }
Now we can create an instance with a short name and get the values from that:
$roles = new MyProject_Authorization_RBAC_Role; if ($role == $roles->ADMINISTRATOR())...
All of this just to get shorter names? I little desperate perhaps. So yes, I would like Enums in PHP.
Derick | 11/05/2008, 04:33
Hei,
if you want something added to PHP you should do the following things:
1. Do your homework on it thoroughly
2. Write an RFC like http://wiki.php.net/rfc/traits (Template is here: http://wiki.php.net/rfc/template)
3. Send it to internals@lists.php.net
Your blog has no meaning for the PHP developers, as they're way to busy with other things - remember that.
Johannes | 11/05/2008, 04:52
but it's so easy to use a blog and you tell everybody you have something to say!
Now to the real question: Take a look at pecl/spl_typesand the SplEnumclass in there, that should help.
Sean Coates | 11/05/2008, 07:56
... or just use a proper error_reporting level:
php -d'error_reporting=E_ALL' -r '$foo = array("bar"=>1); echo $foo["baz"];'
Notice: Undefined index: baz in Command line code on line 1
dagfinn | 11/05/2008, 14:53
@Derick: Did you somehow find this blog post provocative or offensive? I seems strange to me that someone who claims my blog has no meaning would post a comment on it. For the record and in case there might be a misunderstanding, let me assure you that this post is not intended as critical of the PHP developers or their work.
I also realize that there are official ways of proposing new features in PHP, but I can't see the contradiction between that and other ways of discussing them. I probably want to think more about it, but thanks for the pointer.
Ben Ramsey | 11/05/2008, 16:50
I tend to agree that enums would be nice in PHP, as I've found myself wanting them on occasion, but I don't see how they would easily fit into the "PHP way." In order for an enum to work well, you define it with a type that specifies the enum:
class MyProject_Authorization_RBAC_Role
{
public enum Role { REGULAR, WEBMASTER, ADMINISTRATOR };
}
So, now REGULAR is a special constant that has the properties and methods defined on the Role enum. In order for this to work, PHP would need type-hinting for class properties. Not a big deal, but I would argue that you could simply create a Role class instead of an enum and set public properties (similar to what you show) on the MyProject_Authorization_RBAC_Role class, instead, that get initialized in the constructor:
class MyProject_Authorization_RBAC_Role
{
public $REGULAR;
public function __construct()
{
$this->REGULAR = new Role('REGULAR');
}
}
You might even be able to do some Singleton magic and use public static properties to get it even closer to how the enum would work.
However, this still would not solve the issue with wanting shorter names:
MyProject_Authorization_RBAC_Role::$REGULAR
And I would also argue that the purpose of an enum is not to provide a means to having shorter names but, rather, as a way to quickly set up constants on an object with a specific datatype (defined by the enum definition, as in the case of Java).
Still, it may be a feature worth pursuing. I'll take a look at the pecl/spl_type extension to see how they implement enums there.
Ben Ramsey | 11/05/2008, 17:00
I also meant to point out that, while it may be obvious to many, not everyone will notice that this is what an enum is essentially doing. When you do this:
public enum Role { REGULAR, WEBMASTER, ADMINISTRATOR };
Think of it like this:
constant REGULAR = new Role(0);
constant WEBMASTER = new Role(1);
constant ADMINISTRATOR = new Role(2);
Obviously, this isn't possible in PHP right now, but it illustrates how to think of enums. :-)
You would now have constants that have been initialized as the Role "class," and you can statically call them on the class and access their methods:
MyProject_Authorization_RBAC_Role::REGULAR->getPerms()
Perhaps I should've written my own blog post since my response has turned out to be pretty long. :-)
Philip Olson | 11/05/2008, 20:10
These days some people write blog posts instead of using official means like writing an RFC, a mailing list, and/or filling out a bug report. I think all Derick is saying is don't expect this feature request to be remembered without using official means.
And on a related topic, what bugs me [and likely others] most is when people blog about a bug and essentially scream "I found a bug! I found a bug! I found a bug!!!" which ends up on PHP Planet and, well, it's annoying. Not that you did that... but just saying.
dagfinn | 11/05/2008, 22:43
@Ben Ramsey: I can see I need to think more about how I would want enums to actually work in PHP. I may be giving the impression that I have strong opinions while actually I'm just thinking out loud.
Nick | 12/05/2008, 07:55
Instead of using an object just for that - which is an extra overhead to the server - you can use constants. Here is an example :
define ( 'ADMINISTRATOR', 1 );
define ( 'REGULAR', 2 );
if ( $user == ADMINISTRATOR ){
....
}
Nick Lo | 12/05/2008, 15:29
@Derick: "Your blog has no meaning for the PHP developers, as they're way to busy with other things - remember that." Similarly many developers (and I don't just mean PHP developers) have little time for the PHP internals as they're way too busy with other things!
I think it was quite clear that Dagfinn was merely raising a topic of conversation which in many ways IS a way to "do your homework" by inviting different ideas.
Jeff Ray | 12/05/2008, 22:31
I agree with Nick Lo that promoting discussion is a good way to "do your homework". Just because someone hasn't submitted a bug or change request yet, that doesn't mean they won't eventually submit one after having some good pier review of the concern. Lay off guys...
On topic, I thing Enums would be a handy thing as well. Is it critical? No. Would it be useful in some situations? Yes.
I would say that there are multiple ways to get around enums not being present, and there are probably more times than not that a constant or a static constant class would be an equally functional fit. But there are times when you can just tell as a programmer, that a situation is ideal for enums, and finding a workaround just seems awquard.
It would be good to have them. Does the absence of enums detract from the functionality of the language? Probably not.
dagfinn | 12/05/2008, 22:35
One (probably last) comment to the off-topic discussion started by Derick. Expressions like "meaningless" and "do your homework" give (me, and probably others) an impression of implied critcism. If that was the intention, it's not clear and specific enough to be useful to me as such. So I will choose to assume that the impression is a misunderstanding, and that Derick's intention was simply to give information.
tawfiq | 21/05/2008, 00:48
if(ereg("ADMINISTRATOR",$roles))
please go to be enums in php
and than go to the hell
stereofrog | 23/05/2008, 04:43
Hi
finally got time to click your sig on sitepoint. Nice blog you have here!
I understand your concerns about strings vs constants. I don't think the problem with "if($role == 'administrator')" is that is can be misspelled (so can the constant too), but it just "feels" wrong. "Look, it's quoted, it a literal value and we dont like literals in our code". What actually would be helpful here is a rubys interning operator (colon). :foobar in ruby basically says "I dont care how exactly this is stored, the point is when I'm using this here and there I'm referring to the same thing"
dagfinn | 23/05/2008, 05:26
Thanks. I see your point; it does feel wrong. My point is avoiding bugs that are hard to find. That's why I want to get a hard, loud error message when I misspell the role name. Using error_reporting() as someone suggested is not quite strong enough.
| « | September 2008 | » | ||||
|---|---|---|---|---|---|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | ||||
Re: I want enums in PHP
netcelli | 11/05/2008, 04:04
Yea it's good idea to have enums in PHP. I thought the same thing when I was working with user rights with C++!