tags:

views:

99

answers:

4

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? Thanks in advance.

A: 

Isn't this: http://stackoverflow.com/questions/402215/php-readonly-properties approach easier?

It seems to me you try to misuse constants.

MartyIX
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
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
how eval would be helpful here?
CM
A: 

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

if ( $file_exists )
{
    define('MYCONSTANT', 'YEAH');
}
else
{
    define('MYCONSTANT', 'NOPE');
}
Azeem.Butt
No it shouldn't, because it's the answer to his question.
Azeem.Butt
@NSD no, it isnt. You cannot use define in a class. And setting constant values conditionally is misusing constants for variables.
Gordon
You can use it in a class method--like a constructor. Same effect, less noise. Next argument?
Azeem.Butt
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
@NSD time to learn what the "class constant" is.
Michał Mech
If that was the point then it seems odd that it never found its way into the original question.
Azeem.Butt
@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
A: 

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

elias
Yes I know about this but I am searching for some work around of this problem
CM
+2  A: 

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
He didn't say it was variable, he said it was conditional, which is why the define function exists.
Azeem.Butt
@NSD the OP explicitly states *for lets say USERNAME constant, value can be either xyz or abc*. how is that not variable?
Gordon
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
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
@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
@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
@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
@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
@Gordon I can not change it now as its affecting lot of things.
CM
@CM sounds like the perfect opportunity to start writing unit-tests for these things ;)
Gordon
@Gordon Thanks Gordon :).. it seems I don't have that much reputation to give you vote.
CM
@NSD Nobody is wasting time here.
CM