How to check does array key exist in defined constant array [PHP 7 define()]
Asked Answered
O

1

5

PHP7 brought possibility define array constants with define(). In PHP 5.6, they could only be defined with const.

So I can use define( string $name , mixed $value )) to set array of constants, but it seems that it forgot to bring also upgrade of defined ( mixed $name ) along since it still only accepts string value or am I missing something?

PHP v: < 7 I had to define every animal separately define('ANIMAL_DOG', 'black');, define('ANIMAL_CAT', 'white'); etc. or serialize my zoo.

PHP v: >= 7 I can define entire zoo which is freaking awesome, but I can't find my animal in the zoo as simply I can find single ANIMAL. It is reasonable in the real world, but here's supplementary question if I haven't miss something.

Is that intentional that defined(); does not accept array?. If I define my zoo...

define('ANIMALS', array(
    'dog' => 'black',
    'cat' => 'white',
    'bird' => 'brown'
));

... why can't I find my dog simply defined('ANIMALS' => 'dog');?

1. Prints always: The dog was not found

print (defined('ANIMALS[dog]')) ? "1. Go for a walk with the dog\n" : "1. The dog was not found\n";

2. Prints always: The dog was not found and when dog really does not exist shows Notice + Warning

/** if ANIMALS is not defined
  * Notice:  Use of undefined constant ANIMALS - assumed ANIMALS...
  * Warning:  Illegal string offset 'dog'
  * if ANIMALS['dog'] is defined we do not get no warings notices
  * but we still receive The dog was not found */
print (defined(ANIMALS['dog'])) ? "2. Go for a walk with the dog\n" : "2. The dog was not found\n";

3. regardless of whether the ANIMALS, ANIMALS['dog'] is defined or not, I get Warning:

/* Warning:  defined() expects parameter 1 to be string, array given...*/  
print defined(array('ANIMALS' => 'dog')) ? "3. Go for a walk with the dog\n" : "3. The dog was not found\n";

4. I get Notice if ANIMALS['dog'] is not defined

/* Notice: Use of undefined constant ANIMALS - assumed 'ANIMALS' */
print (isset(ANIMALS['dog'])) ? "4. Go for a walk with the dog\n" : "4. The dog was not found\n";

5. So am I correct that there is only one option left then?

print (defined('ANIMALS') && isset(ANIMALS['dog'])) ? "Go for a walk with the dog\n" : "The dog was not found\n";
Oink answered 13/2, 2016 at 12:1 Comment(8)
Well ANIMALS is the constant; and the array key dog is simply part of the value that is defined for that constant; so it seems logical that defined() won't check for a value within the constant, only for the constant itself; so yes, logically this should be a two step checkBourges
@Mark Well for me that seems logical only in extent as PHP v < 7 define should only accept string ;)Oink
PHP <7 would accept any scalar, not just string; but to check the type and whether it was defined was still a 2-step process.... define('TESTMODE', true); if (defined('TESTMODE') && TESTMODE) { ... }Bourges
If in the future constants may evaluate to scalar values, arrays or objects then One could get similar question and want to easily check objects property. Don't they? instead of (defined('ANIMALS') && isset(ANIMALS->dog))Oink
The principle still holds it isn't ANIMALS['dog'] that's defined as the constant, it's ANIMALS.... the fact that a constant is defined doesn't tell you anything about the value of that constant, simply the fact that it is defined..... you always have (and likely always will) need to make two separate tests, one for whether the constant (name) is defined, and another to identify facets of the value of the constant.... there isn't any shortcut to do both tests in a single call....Bourges
there isn't anything forgotten, defined() still does exactly what it's supposed to do, test for the existence of a Constant, nothing more and nothing less, and nothing to do with any value assigned to that constant.... Checks whether a given named constant existsBourges
@Mark Well that's the thing I guess that I consider ANIMALS['dog'] as constant in kind of constant namespace ANIMALS instead of taking it as just a array key.Oink
I guess what you want is an equivalent of isset for constants which works like isdefined(ANIMALS['dog']), and the answer is it doesn't exist at the moment. You can easily implement it as userspace function, and you can suggest it to the PHP dev team for implementation if you're convinced it's an oversight.Leid
G
10

PHP 7 allows you to define a constant array, but what is being defined as a constant in that case is the array itself, not its individual elements. In every other regard the constant functions as a typical array, so you'll need to use conventional methods to test for the existence of a specific key within it.

Try this:

define('ANIMALS', array(
    'dog'  => 'black',
    'cat'  => 'white',
    'bird' => 'brown'
));

print (defined('ANIMALS') && array_key_exists('dog', ANIMALS)) ?
    "Go for a walk with the dog\n" : "The dog was not found\n";
Gilburt answered 13/2, 2016 at 14:6 Comment(1)
That would indeed right to use when you expect ANIMALS to be array as key => val pair, however if you have define('ANIMALS', array('dog','cat','bird')); you can't use array_key_exists and could only use option 5 isset or in_array instead.Oink

© 2022 - 2024 — McMap. All rights reserved.