# Feasibility of additional support around constants.

- Thread: https://externals.io/message/50125
- Original archive: https://news-web.php.net/php.internals/50125
- Started by Richard Quadling on 2010-11-08T12:33:19+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #50125 — Richard Quadling — 2010-11-08T12:33:19+00:00

URL: https://externals.io/message/50125#50125

Hi.

Some extensions provide a lot of constants. Currently, there is no
mechanism to group related constants.

Whilst many constants are prefixed with the extension name, within
that group, there is no standardised way to further group them.

Also, there is no way to reverse the mechanism. From a value, what is
the constant's name that would have been used in userland code?

It would be useful to have the ability to
tag/group/block/enum/const-array/etc. to form a collection of
constants so that from userland, you can easily identify the name of
the constant you have received.

I suppose, this is mainly useful where the userland code is a layer of
some sort, something that has to validate or extrapolate values
further down the chain and report back on them.

There are 3 main uses I can think of which would be useful.

1 - Validating that the value received is in a collection of known
constants. This would allow for new constants to be added without the
layer having to be amended to verify the value. If it isn't in the
group - it's invalid.
2 - For a constant value, report back the actual name of the constant.
The user supplied the value of 4 to the function. The function failed
for some reason and in the ensuing exception report, showing the name
of the constant would be extremely useful. Not all the extensions
document the value of the constants, so knowing what 4 is in't
instantly available.
3 - If the collection is a set of bitmasks (error_reporting for
example), then report back the constants that make the value.


This can all be done in userland code with some degree of simplicity,
but amending the code for each new constant seems that it should be
unnecessary.


Now, you may think, why not use Reflection? Yes. I have done that but
you can't easily group the constants. There are many constants set to
the value of 2 (for example).

All of these are from the standard extension.

   Constant [ integer `CONNECTION_TIMEOUT` ] { 2 }
   Constant [ integer `INI_PERDIR` ] { 2 }
   Constant [ integer `PHP_URL_PORT` ] { 2 }
   Constant [ integer `PHP_ROUND_HALF_DOWN` ] { 2 }
   Constant [ integer `INFO_CREDITS` ] { 2 }
   Constant [ integer `CREDITS_GENERAL` ] { 2 }
   Constant [ integer `ENT_COMPAT` ] { 2 }
   Constant [ integer `STR_PAD_BOTH` ] { 2 }
   Constant [ integer `PATHINFO_BASENAME` ] { 2 }
   Constant [ integer `LC_CTYPE` ] { 2 }
   Constant [ integer `SEEK_END` ] { 2 }
   Constant [ integer `LOCK_EX` ] { 2 }
   Constant [ integer `STREAM_NOTIFY_CONNECT` ] { 2 }
   Constant [ integer `STREAM_NOTIFY_SEVERITY_ERR` ] { 2 }
   Constant [ integer `STREAM_FILTER_WRITE` ] { 2 }
   Constant [ integer `STREAM_CLIENT_ASYNC_CONNECT` ] { 2 }
   Constant [ integer STREAM_CRYPTO_METHOD_SSLv23_CLIENT ] { 2 }
   Constant [ integer `STREAM_SHUT_RDWR` ] { 2 }
   Constant [ integer `STREAM_PF_INET` ] { 2 }
   Constant [ integer `STREAM_SOCK_DGRAM` ] { 2 }
   Constant [ integer `STREAM_PEEK` ] { 2 }
   Constant [ integer `FILE_IGNORE_NEW_LINES` ] { 2 }
   Constant [ integer `FNM_PATHNAME` ] { 2 }
   Constant [ integer `PSFS_PASS_ON` ] { 2 }
   Constant [ integer `PSFS_FLAG_FLUSH_CLOSE` ] { 2 }
   Constant [ integer `LOG_CONS` ] { 2 }
   Constant [ integer `EXTR_PREFIX_SAME` ] { 2 }
   Constant [ integer `SORT_STRING` ] { 2 }
   Constant [ integer `ASSERT_CALLBACK` ] { 2 }
   Constant [ integer `STREAM_IGNORE_URL` ] { 2 }
   Constant [ integer `STREAM_URL_STAT_QUIET` ] { 2 }
   Constant [ integer `STREAM_OPTION_READ_BUFFER` ] { 2 }
   Constant [ integer `STREAM_BUFFER_FULL` ] { 2 }
   Constant [ integer `IMAGETYPE_JPEG` ] { 2 }
   Constant [ integer `DNS_NS` ] { 2 }



I think that extending the struct _zend_constant to include a constant
group number in addition to the existing module number, should be
enough in terms of storage (an extra int per constant). The
REGISTER_xxxx_CONSTANT macros and their module specific clones would
been to be extended to allow for the constant group property to be
set, though a mechanism to supply a default for the constant group
would be a good thing I think so that untouched extensions still
report their constants as belonging to the to the unassigned group.

I guess that covers the ground work.

There would need to be a few new built-in functions to allow access to
the name and for the decomposition of the bitmask to its constituent
values.

Each extension would need to be amended to provide the additional
facilities - though, hopefully, this would be nothing more than adding
the constant group number to the constant creation macro call.

And the `get_defined_constants()` function could be amended to from ...

array get_defined_constants ([ bool $categorize = false ] )

to

array get_defined_constants ([ int $categorization_depth = 0])

where 0 is none, 1 is the same as true at the moment and 2 would be by
extension and then by each group.


If the additional grouping was alpha, rather than numeric, that would
help further I think (removing the magic numbers).


Is this anything that is ...

a - Useful
b - Doable

Regards,

Richard Quadling.




-- 
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY

---

## #50131 — Richard Lynch — 2010-11-09T05:17:19+00:00

URL: https://externals.io/message/50125#50131 · In reply to: #50125

> 1 - Validating that the value received is in a collection of known
> constants. This would allow for new constants to be added without the
> layer having to be amended to verify the value. If it isn't in the
> group - it's invalid.

Generally-speaking, it's valid if it's between 0 and the largest
value, rather than being in an array/list...

And, yes, updating the code to check this is really hard, unless
you're smart enough to do something like:

define('FOO_0', 0);
define('FOO_1', 1);
.
.
.
define('FOO_42', 42);
define('FOO_MAX', 42);

and then your check is on FOO_MAX, which you update when you add
another constant.

> 2 - For a constant value, report back the actual name of the constant.
> The user supplied the value of 4 to the function. The function failed
> for some reason and in the ensuing exception report, showing the name
> of the constant would be extremely useful. Not all the extensions
> document the value of the constants, so knowing what 4 is in't
> instantly available.

It doesn't really take a lot of effort to copy/paste the constant
names and echo out their values...

Not that you *should* do that, as those might change in a new release,
if there is some kind of meaningful order to those constants by name,
and one is INSERTED and they were never intended to be stored
externally, much less embedded in your code...

In fact, the whole point of USING constants will be violated by using
the magic number to reverse-engineer the "name" of the constant, if
you think about it for a bit.

> 3 - If the collection is a set of bitmasks (error_reporting for
> example), then report back the constants that make the value.

Here the valid combinations may be subject to some
application-specific logic where the range would have holes in it...
E.g., 1 & 4 might be an invalid bitmask, where 1&2 and 1&8 is
perfectly valid...  So I can see where this maybe needs a list of
known valid values, sometimes...

But the library itself should take care of this, and provide a
function to check the validity, not the app layer.

It's putting the burden on every single app that uses the library,
which is just fundamentally wrong.

> Now, you may think, why not use Reflection? Yes. I have done that but
> you can't easily group the constants. There are many constants set to
> the value of 2 (for example).

If you don't know which extension generated the error in the first
place, you are in REAL trouble...

So just knowing the extension and 2 ought to tell you which constant
it is...

In the rare occasion where I felt the need to reverse-engineer this,
an array like $foo_constants[ FOO_1 ] = 'FOO 1'; did the trick for me.
 And, yes, updating that when constants are added is somewhat painful,
but then you'll have to update SOMETHING somewhere to get meaningful
text out of it, unless you get the parser to just slap the first
parameter to `define()` into the zval...

So instead of a "group number", you'd have the zval storing
'INFO_CREDITS' (for example) somehow for the 2 that goes with
 `phpinfo()`...

> a - Useful

Honestly, not really...

I can see why it looks useful at first, but it just violates too many
principles to implement, at least as you describe it...

And storing the constant name in the zval at the time of the `define()`...

Come to think of it, whatever 'defined' does to look up the answer
implies that PHP is already storing the constant name *somewhere*...

How you would tie that back to the value of the constant is beyond me,
but doing that in the 'define' C codebase that seems far more simple
than making up some new "group number"...

Of course, I'm not gonna be the guy writing that code :-)

> b - Doable

Seems like a lot of effort for minimal benefit to this naive reader.

-- 
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FS9NLTNEEKWBE

---

## #50132 — Peter Lind — 2010-11-09T06:39:33+00:00

URL: https://externals.io/message/50125#50132 · In reply to: #50131

*snip*

Seems to me that some of this could be handled with a custom built
function wrapping
http://dk2.php.net/manual/en/function.get-defined-constants.php

Regards
Peter

-- 
<hype>
WWW: plphp.dk / plind.dk
LinkedIn: plind
BeWelcome/Couchsurfing: Fake51
Twitter: kafe15
</hype
