If you’ve spent any time looking at PHP code, then you’ve seen defines and variables
Defines
A define looks like this:
define('SOMETHING', true);
This makes a global constant that can be used anywhere. In the case of WordPress, it means they can be used across multiple plugins or themes. This is very useful if you make a suite of plugins that all have the possibility of using the same API key. Then you can tell a user to put define('MY_PLUGIN_API', '123456');
in their wp-config.php
file, and tell your code to check for the define.
A define also cannot be redefined. If you call it twice, you get errors, so you should be as unique as possible when creating yours.
Variables
A variable, meanwhile, looks like this:
$SOMETHING = true;
Variables only exist where they are, so if I have one in one function, I may not be able to call it in another. You can make global variables if needed, and in fact if you don’t, the variable won’t be available to all functions.
Which Should I Use?
Keeping in mind that defines are constants and variables are, well, variables, the idea is that a constant should be used for things that should not change in the running of the code. It also makes your code easier to maintain if the things that must be constant are explicitly so.
So what’s a good define? Actually not really this:
define('MY_PLUGIN_VERSION', '1.0');
This is a constant, it’s something you should be setting and it shouldn’t be overwritten, but actually I’d want to make it a database field to check on before upgrading. Remember, you should be changing that define on upgrade, so having it be a declared constant is a little odd. Now that said, it is a good one when you consider you don’t want someone to willy-nilly override it. Except … what if you do? What if you want someone to be able to change it back to re-run an upgrade?
So then really not this either:
define( 'MY_PLUGIN_PATH', plugin_dir_path( __FILE__ ) ); define( 'MY_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); include( MY_PLUGIN_PATH . 'lib/asset.php') ;
Someone’s probably thinking that their plugin directory is a constant and, thus, should be defined like that. Maybe, but it’s a pointless define in WordPress. You already have plugins_url()
(which this example isn’t using) but it’s really where people use that code that makes no sense. That’s why I included the second line there. That’s what they use it for, and it means two lines of code for one function call.
This actually magically becomes a good define when you have a complex plugin with multiple files and you need to grab the main plugin directory in sub-files. But if your plugin is one file (and yes, that’s where I see it the most), it’s overkill.
This is a good define:
define('MY_PLUGIN_APIKEY', '123456');
But that should never be in your code itself. Not for WordPress at least. That should be in the wp-config.php
, like I mentioned before.
Basically … there aren’t great reasons to use defines unless you want things that never change. define('MY_PLUGIN_SUPPORT_HOME','http://help.example.com');
would make sense to me, as would other contact info you want to make sure is never subverted.
What do you think define is best for?
I’m interested to hear what you guys like to use defines for. I’m certainly guilty of using them for some pretty silly reason.
Comments
8 responses to “Defines, Variables, and Plugin Dirs”
Within a plugin, I use constants for strings which are constant, but need generated more than once (otherwise I’d just use them directly), or for setting strings I’d like overridden via wp-config.php (this is uncommon though, since you would normally prefer people to use filters).
Defines are great practice for reusable constants. It makes refactoring much easier, works with IDEs auto-complete and adds sense to “magic” values. For example, instead of using 60*60*24, defining a constant it’s better practice:
define(WP__MY_DAY_IN_SEC, 60*60*24);
– Creating functions instead of defines it’s a waste of run-time resources (especially when used a lot in the code).
– Storing that on local variable is also bed practice when used in more than one function.
– Using global variable is also not good since you’ll need to set the global directive in every function you want to use the value at, plus global variable value could be modified.
@Vova Feldman: That’s an interesting statement:
> Creating functions instead of defines itβs a waste of run-time resources
Can you cite a source on that? What’s the run-time difference between these:
define(WP__MY_DAY_IN_SEC, 60*60*24);
and
$plugin_my_day_in_sec = 60*60*24;
and just
(60*60*24)
(inline in the code)I agree that when you’re reusing things a lot, having the math in the code would be a pain and hard to change later if you decide a day is 24 hours 37 minutes and 22 seconds long because you’re on Mars. But how much run-time are we talking about?
@Ipstenu (Mika Epstein): When you define a function instead of a constant it would look like:
So every time you’ll call plugin_my_day_in_sec() it will have to allocate resources for the call stack + the execution of the multiplier operator.
If you define:
in every function you would need to use it, it’s just code redundancy.
Regarding refactoring, the day in seconds is not good example, but there are many situations when you do want to change constants for various reasons. For example a case where you protect your DB queries by adding a default limit:
and later you would like to change that.
It’s all real cases, not just my imagination π
@Vova Feldman: This is the only part I question:
You don’t have to define it IN a function, though. That’s my point. If you toss this in a singleton:
var $my_day_in_secs = 60*60*24;
Then I can call
$this->my_day_in_secs
or by the Singleton name if needs be.Is there a speed difference for that?
(BTW code html tags work)
Your solution is great for cases when you have only one class. In complex projects with multiple classes, files… when you need to use the constant in different classes, that’s when you need the define directive. In addition, the better practice when using constants is actually setting them as constants. When you configure it as a variable, it could potentially be modified, which is not what you want. PHP 5.3 actually have class const directive, which is the local version of define in a class scope.
@Vova Feldman: I promise I’m not asking all this to be obtuse.
Multiple classes so I call
$CLASSNAME->my_day_in_secs
since in general, I’ve got at least one class that is the master class used by all. Is that because I’m odd?And yes, I meant to say const π I was pulling from memory on the iphone. Bad idea.
I guess you mean CLASSNAME::my_day_in_secs? or it could be CLASSNAME::instance()->my_day_in_secs with a singleton. In any case, you can do that, and more or less it’s the same performance/speed/resources (the difference is negligible).
Having said that, since you should always strive to make code clear and self-readable, when you use CLASSNAME::my_day_in_secs besides the functional usage, there’s also some semantic meaning. When professional developer looks at that line s/he can understand:
1. Since the whole concept of OOP is providing context to objects/properties/methods, from your code my_day_in_secs is related to CLASSNAME (if your class is Time, then it makes sense, if it’s Dog then it probably don’t).
2. Since it’s lower case, it’s a static variable and as an external user of your class, since it’s a variable I can change it (probably not something that you want for constants).
Hope it helps π