6

I am using one separate file for all constants of my PHP application.

class constants
{
    const USERNAME = 'abc';
    /*
      ⋮
    */
}

For lets say USERNAME constant, value can be either xyz or abc based on file exists check. If xyz file exists USERNAME value would be xyz. How can I do this check in my constants class?

hakre
  • 193,403
  • 52
  • 435
  • 836
CM.
  • 670
  • 1
  • 6
  • 25

4 Answers4

6

If the value of the constant is variable, then it is not a constant, but a variable.

Since you are (correctly) trying to keep your application stuff capsuled and away from the global scope, you might be interested in the Registry Pattern. A Registry is basically a glorified array that stores whatever you throw into it and is globally accessible throughout your application.

Some resources:


EDIT If you are truly desperate and have to have the constant redefined, you can use

Runkit might not be available if you are on shared hosting and I consider needing it a code smell, but here is how you'd basically do it (in your bootstrap)

if ( file_exists('xyc') ) {
    runkit_constant_redefine('Constants::USERNAME', 'xyz');
}

EDIT Some more options (all of which not exactly pretty either):

class Abc { const FOO = 1; const BAR = 2; }
class Xyz extends Abc { const FOO = 2; }
class_alias(file_exists('abc') ? 'Abc' : 'Xyz', 'Constants');

For this you would rename your current constants class to Abc and add a second class Xyz to extend it and overwrite the USERNAME constant (FOO in the example). This would obviously break your code, because you used to do Constants::USERNAME, so you have to create an alias for the former class name. Which class Constants will point to, is decided with the conditional check. This requires PHP5.3.

A pre-5.3 solution would be to simply save the Constants class file under two different names, e.g. abc_constants.php and xyz_constants.php, modify the latter accordingly to hold USERNAME xyz and then include either or depending on the file check.

Or replace the value of USERNAME with a placeholder and instead of including the class you load it into a variable as a string. Then you replace the placeholder according to the filecheck result and eval the string, effectively including the class this way.

But I have to say it again: I strongly suggest refactoring your code over using these.

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 1
    He didn't say it was variable, he said it was conditional, which is why the define function exists. – Azeem.Butt Apr 17 '10 at 18:03
  • @NSD the OP explicitly states *for lets say USERNAME constant, value can be either xyz or abc*. how is that not variable? – Gordon Apr 17 '10 at 18:08
  • As is usually the case on SO, the question was edited by someone who didn't pay a lot of attention to it. What he actually said was that it was conditionally defined based on whether or not a file existed. Since it's unlikely that this file is going to be created and deleted repeatedly at runtime, this is overkill unless you just want to impress your boss with your line count at the end of the day. – Azeem.Butt Apr 17 '10 at 18:19
  • Thing is this constant has been used in several files of my application and its value can be either 'abc' or 'xyz' based on file exists in system.One solution I have is I can create 2 separate constants (USERNAME = 'abc'; //current code) (USERNAME_NEW = 'xyz' ; //add new constant) USERNAME_NEW gets always high priority so if its defined use it else go for USERNAME but I dont want to create ugly code by putting if-else condition everywhere just for constant name check. So rather than creating new constant , I feel its good to change value of USERNAME constant itself. – CM. Apr 17 '10 at 18:44
  • @NSD agree to disagree. A constant that gets it's value based on a condition, even when immutable after that, is not a constant in my book, because it *can* hold variable values. – Gordon Apr 17 '10 at 18:57
  • 1
    @CM no offense, but to me it sounds like the code already is ugly. Either USERNAME is a fixed value or it isn't. If it isn't don't make it a constant. If that is how it is in your code right now, then consider refactoring it. – Gordon Apr 17 '10 at 19:01
  • @Gordon I think I have not explained my scenario properly..sorry for that. In my case USERNAME will always be fixed after bootstrapping the application. Its only a matter of telling my application either to go for 'abc' or 'xyz'. Once application has find out specific value, it won't change after that through out the application. Hope it makes sense here. – CM. Apr 17 '10 at 19:17
  • @CM yes, I understood that right from the start. The thing is, I don't think a constant should have anything but *one* fixed value. Your USERNAME is constant in that it is *immutable* after bootstrap, but it is not constant in it's value to start with. It can be either *abc* or *xyz*. Can't you make USERNAME a static property in the class instead? – Gordon Apr 17 '10 at 19:30
  • @Gordon I can not change it now as its affecting lot of things. – CM. Apr 17 '10 at 19:49
  • @CM sounds like the perfect opportunity to start writing unit-tests for these things ;) – Gordon Apr 17 '10 at 19:55
  • @Gordon Thanks Gordon :).. it seems I don't have that much reputation to give you vote. – CM. Apr 18 '10 at 07:08
  • Thanks Gordon, another gem of knowledge + *if-you-really-want-hack* + refactoring/unit test advice. I wish there was a PM system on SO in order to communicate such feelings, but I guess comments will do for now – wadkar Oct 24 '11 at 07:05
0

Isn't this: PHP Readonly Properties? approach easier?

It seems to me you try to misuse constants.

Community
  • 1
  • 1
MartyIX
  • 27,828
  • 29
  • 136
  • 207
  • Actually when I designed application, there was only one value supposed to be there for one constant. And to make one single constant file for all constants seemed to me simple approach. And now because of some requirement changes, It can vary depending on file exists check. I can not change now constants file as I have to also support backward compatibility. – CM. Apr 17 '10 at 17:46
  • I see. Well and variants of file with constants class? If it's only a matter of USERNAME then it will be ok. Otherwise it's unusable. Or eval function may do the trick. – MartyIX Apr 17 '10 at 18:11
  • how eval would be helpful here? – CM. Apr 17 '10 at 18:29
0

http://us2.php.net/manual/en/function.define.php

if ( $file_exists )
{
    define('MYCONSTANT', 'YEAH');
}
else
{
    define('MYCONSTANT', 'NOPE');
}
Azeem.Butt
  • 5,855
  • 1
  • 26
  • 22
  • No it shouldn't, because it's the answer to his question. – Azeem.Butt Apr 17 '10 at 17:38
  • @NSD no, it isnt. You cannot use define in a class. And setting constant values conditionally is misusing constants for variables. – Gordon Apr 17 '10 at 18:08
  • You can use it in a class method--like a constructor. Same effect, less noise. Next argument? – Azeem.Butt Apr 17 '10 at 18:13
  • You still don't get the point. The OP wants *class constants*, not global constants. The whole point of having the constants in a class is not to litter the global scope with custom constants. – Gordon Apr 17 '10 at 18:16
  • If that was the point then it seems odd that it never found its way into the original question. – Azeem.Butt Apr 17 '10 at 18:35
  • @NSD yeah well, and if the OP wanted to have global constants, then it seems odd this didn't make it into the question either, don't you think. Yet, you do suggest a mechanism for defining global constants. – Gordon Apr 17 '10 at 18:49
0

It's not possible do have conditional constant definitions inside classes.

elias
  • 1,481
  • 7
  • 13