I'd like to organize my constants neatly.
In C++ I would've put enums or variables in a namespace (or more) like so:
namespace foo
{
namespace bar
{
enum herp { derp, sherp, sheep };
}
namespace Family
{
const string mom = "Anita";
const string son = "Bob";
const string daughter = "Alice";
}
}
This would give me the possibility to access them like
int x = foo::bar::derp;
string nameOfMom = foo::Family::mom;
string nameOfSon = foo::Family::son;
How can I implement this in PHP?
As far as the enum is concerned: There is no enum in PHP. You can write an array (which is in fact a HashTable underneath) or you'll have to use a (separate) namespace and/or define a class for that, given that an enum is closer to a class, I'd probably opt for the latter and go ahead and write:
class FakeEnum
{
const DERP = 0;
const SHERP = 1;
const SHEEP = 2;
}
jycr753 already linked this question, and it does show how you could emulate enums in PHP, but if you ask me, that's just taking it that little bit too far. Using a ReflectionClass just to emulate a missing construct is like modifying your car so it can double as a motorcycle.
On to the namespaces:
Namespaces in PHP are relatively "new", and they are not 100% equivalent to C++ namespaces. For one, they can't be nested in the way you are trying. For that, you'll have to resort to declaring classes inside a given namespace, and accept that only allows for 1 additional level.
All things asside, I take it you're looking for something like this:
namespace Foo
{
const FOOBAR = 123;
}
namespace Bar
{
const FOOBAR = 456;
}
namespace Work
{
const FOOBAR = __NAMESPACE__;
include 'global_const.php';
echo 'Global FOOBAR const is: ', \FOOBAR, PHP_EOL,
'Foo::FOOBAR is: ', \Foo\FOOBAR, PHP_EOL,
'Bar::FOOBAR is: ', \Bar\FOOBAR, PHP_EOL,
'Work::FOOBAR is: ', FOOBAR, PHP_EOL;
}
Where the global_const.php file defines a global constant like so:
define('FOOBAR', 'global');//just to be consistent ;-P
The resulting output is:
Global FOOBAR const is: global
Foo::FOOBAR is: 123
Bar::FOOBAR is: 456
Work::FOOBAR is: Work
Of course, in reality, your code will be spread-out over multiple files, and more often than not, you'll only use a single namespace for that file, and use other namespaces (≃ using in C++):
namespace My\Core\Components\Output;
use Foo,
Bar,
My\Core\Components\Input as CoreInput;
use External\Component\Input as HelperInput;
The inconsistencies in the PHP namespacing system are well documented (google search them). But to give you an example, if I start my file with the statements above, the following statement:
$myVar = Foo\SOME_CONSTANT;
resolves to
global namespace (\ for short)
->Foo namespace
-> SOME_CONSTANT
But if I were to remove the use Foo, the same statement resolves to:
\
-> My
-> Core
-> Components
-> Output
-> Foo
-> SOME_CONSTANT
Now that may seem perfectly reasonable, but the same rule does not apply to the core functions: \str_replace or str_replace are both resolved correctly, the only difference is that the latter will first perform a lookup for a function called str_replace in the current namespace, to then fall-back to the global namespace.
Ok, with some "goodwill" you could argue that this, too, is fairly predictable behaviour. Sadly, strangely or maliciously, PHP does not behave in the same way when using its core objects (like DateTime, stdClass, Exception or PDO...).
Take the mysqli_* extension, for example: you can use its procedural API throughout all of your namespaces and be a happy camper, but if you prefer the OO API, you'll have to use the use statements, or add a backslash whenever you write new \mysqli().
Ok, so PHP has its faults, but of course, we all know that much, as for your question, I believe I you have an answer now, and for me to continue this rant would be utterly pointless. Everything you need to know about namespaces can be found in the manual, BTW
Related
What I wanted to is to create class instance from string in Symfony framework to use Doctrine Repository. Here is my code block:
$type = "SomeClassName";
$productType = $this->productTypeProvider->getProductType($product->getBarcode());
$repository = $this->doctrine->getRepository($type::class);
I want to use SomeClassName::class above but it gives me the following error. Any help would be appeciated:
Cannot use "::class" on value of type string (500 Internal Server Error)
As mentioned above, using the full class name worked perfectly.
To understand why this doesn't work, it's useful to have some background on how namespaces are implemented in PHP:
Every class, interface, trait, and enum has a "fully-qualified class name" (FQCN), which can contain zero or more namespace separators (\)
A particular file, or code-block, can have a "current namespace" defined.
Within that block, you can have any number of use statements, which provide short-hands within the scope of that file.
The expansion of the current namespace, and the currently in-scope use statements, happens at compile-time - in case you're not aware, PHP is a compiled language, the compiler is just invoked automatically, for a single file.
The ::class syntax is part of this compile-time expansion: it substitutes any relevant use statements or current namespace, and then treats the result as a string. In other words, this:
namespace Foo\Bar;
use Something\Else;
use Something\Else\Again as Alias;
echo Example::class;
echo Else::class;
echo Else\More::class;
echo Alias::class;
Is compiled exactly as though it said this:
echo 'Foo\Bar\Example';
echo 'Something\Else';
echo 'Something\Else\More';
echo 'Something\Else\Again';
Those strings can then be passed around to wherever needs an FQCN.
The key point here is that this all happens before any code in the file is executed. When you tried to write $type::class, the value of $type is something that will only be known at run-time; far too late for the namespace expansion in the compiler to affect it. Theoretically, the compiler could know what you meant by "SomeClassName"::class, but it would be unnecessary extra complexity since you can just write SomeClassName::class instead.
If you are building a string at run-time, you are responsible for turning it into an FQCN.
Note that despite its name, ::class doesn't actually check that the result is a class name, it just does string manipulation based on the current namespace and use statements, so the following are all equivalent:
namespace Example;
use App\Entity; // [1]
use App\Entity\SomeClassName; // [2]
// explicit FQCN
$type = 'App\Entity\SomeClassName';
// straight-forward expansion of [2]
$type = SomeClassName::class;
// expansion of [1]
$type = Entity\SomeClassName::class;
// expand the namespace via [1] then add class name
$namespace = Entity::class;
$type = $namespace . '\SomeClassName';
// expand to a non-existent class, then add more text
$prefix = Entity\So::class;
$type = $prefix . 'meClassName';
In PHP, you can declare constants in two ways:
With define keyword
define('FOO', 1);
Using const keyword
const FOO = 1;
What are the main differences between those two?
When and why should you use one and when use the other?
As of PHP 5.3 there are two ways to define constants: Either using the const keyword or using the define() function:
const FOO = 'BAR';
define('FOO', 'BAR');
The fundamental difference between those two ways is that const defines constants at compile time, whereas define defines them at run time. This causes most of const's disadvantages. Some disadvantages of const are:
const cannot be used to conditionally define constants. To define a global constant, it has to be used in the outermost scope:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
Why would you want to do that anyway? One common application is to check whether the constant is already defined:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const accepts a static scalar (number, string or other constant like true, false, null, __FILE__), whereas define() takes any expression. Since PHP 5.6 constant expressions are allowed in const as well:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const takes a plain constant name, whereas define() accepts any expression as name. This allows to do things like this:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
consts are always case sensitive, whereas define() allows you to define case insensitive constants by passing true as the third argument (Note: defining case-insensitive constants is deprecated as of PHP 7.3.0 and removed since PHP 8.0.0):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
So, that was the bad side of things. Now let's look at the reason why I personally always use const unless one of the above situations occurs:
const simply reads nicer. It's a language construct instead of a function and also is consistent with how you define constants in classes.
const, being a language construct, can be statically analysed by automated tooling.
const defines a constant in the current namespace, while define() has to be passed the full namespace name:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However, arrays will be supported for both cases in PHP 7.
const FOO = [1, 2, 3]; // Valid in PHP 5.6
define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0
Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Summary
Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!
Until PHP 5.3, const could not be used in the global scope. You could only use this from within a class. This should be used when you want to set some kind of constant option or setting that pertains to that class. Or maybe you want to create some kind of enum.
define can be used for the same purpose, but it can only be used in the global scope. It should only be used for global settings that affect the entire application.
An example of good const usage is to get rid of magic numbers. Take a look at PDO's constants. When you need to specify a fetch type, you would type PDO::FETCH_ASSOC, for example. If consts were not used, you'd end up typing something like 35 (or whatever FETCH_ASSOC is defined as). This makes no sense to the reader.
An example of good define usage is maybe specifying your application's root path or a library's version number.
I know this is already answered, but none of the current answers make any mention of namespacing and how it affects constants and defines.
As of PHP 5.3, consts and defines are similar in most respects. There are still, however, some important differences:
Consts cannot be defined from an expression. const FOO = 4 * 3; doesn't work, but define('CONST', 4 * 3); does.
The name passed to define must include the namespace to be defined within that namespace.
The code below should illustrate the differences.
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
The content of the user sub-array will be ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].
=== UPDATE ===
The upcoming PHP 5.6 will allow a bit more flexibility with const. You will now be able to define consts in terms of expressions, provided that those expressions are made up of other consts or of literals. This means the following should be valid as of 5.6:
const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;
You still won't be able to define consts in terms of variables or function returns though, so
const RND = mt_rand();
const CONSTVAR = $var;
will still be out.
define I use for global constants.
const I use for class constants.
You cannot define into class scope, and with const you can.
Also, with const, it actually becomes a member of the class, and with define, it will be pushed to global scope.
I believe that as of PHP 5.3, you can use const outside of classes, as shown here in the second example:
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
NikiC's answer is the best, but let me add a non-obvious caveat when using namespaces so you don't get caught with unexpected behavior. The thing to remember is that defines are always in the global namespace unless you explicitly add the namespace as part of the define identifier. What isn't obvious about that is that the namespaced identifier trumps the global identifier. So :
<?php
namespace foo
{
// Note: when referenced in this file or namespace, the const masks the defined version
// this may not be what you want/expect
const BAR = 'cheers';
define('BAR', 'wonka');
printf("What kind of bar is a %s bar?\n", BAR);
// To get to the define in the global namespace you need to explicitely reference it
printf("What kind of bar is a %s bar?\n", \BAR);
}
namespace foo2
{
// But now in another namespace (like in the default) the same syntax calls up the
// the defined version!
printf("Willy %s\n", BAR);
printf("three %s\n", \foo\BAR);
}
?>
produces:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
Which to me makes the whole const notion needlessly confusing since the idea of a const in dozens of other languages is that it is always the same wherever you are in your code, and PHP doesn't really guarantee that.
Most of these answers are wrong or are only telling half the story.
You can scope your constants by using namespaces.
You can use the "const" keyword outside of class definitions. However, just like in
classes the values assigned using the "const" keyword must be
constant expressions.
For example:
const AWESOME = 'Bob'; // Valid
Bad example:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
To create variable constants use define() like so:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
To add on NikiC's answer. const can be used within classes in the following manner:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
You can not do this with define().
Yes, const are defined at compile-time and as nikic states cannot be assigned an expression, as define()'s can. But also const's cannot be conditionally declared (for the same reason). ie. You cannot do this:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
Whereas you could with a define(). So, it doesn't really come down to personal preference, there is a correct and a wrong way to use both.
As an aside... I would like to see some kind of class const that can be assigned an expression, a sort of define() that can be isolated to classes?
In PHP, you can declare constants in two ways:
With define keyword
define('FOO', 1);
Using const keyword
const FOO = 1;
What are the main differences between those two?
When and why should you use one and when use the other?
As of PHP 5.3 there are two ways to define constants: Either using the const keyword or using the define() function:
const FOO = 'BAR';
define('FOO', 'BAR');
The fundamental difference between those two ways is that const defines constants at compile time, whereas define defines them at run time. This causes most of const's disadvantages. Some disadvantages of const are:
const cannot be used to conditionally define constants. To define a global constant, it has to be used in the outermost scope:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
Why would you want to do that anyway? One common application is to check whether the constant is already defined:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const accepts a static scalar (number, string or other constant like true, false, null, __FILE__), whereas define() takes any expression. Since PHP 5.6 constant expressions are allowed in const as well:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const takes a plain constant name, whereas define() accepts any expression as name. This allows to do things like this:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
consts are always case sensitive, whereas define() allows you to define case insensitive constants by passing true as the third argument (Note: defining case-insensitive constants is deprecated as of PHP 7.3.0 and removed since PHP 8.0.0):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
So, that was the bad side of things. Now let's look at the reason why I personally always use const unless one of the above situations occurs:
const simply reads nicer. It's a language construct instead of a function and also is consistent with how you define constants in classes.
const, being a language construct, can be statically analysed by automated tooling.
const defines a constant in the current namespace, while define() has to be passed the full namespace name:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However, arrays will be supported for both cases in PHP 7.
const FOO = [1, 2, 3]; // Valid in PHP 5.6
define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0
Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Summary
Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!
Until PHP 5.3, const could not be used in the global scope. You could only use this from within a class. This should be used when you want to set some kind of constant option or setting that pertains to that class. Or maybe you want to create some kind of enum.
define can be used for the same purpose, but it can only be used in the global scope. It should only be used for global settings that affect the entire application.
An example of good const usage is to get rid of magic numbers. Take a look at PDO's constants. When you need to specify a fetch type, you would type PDO::FETCH_ASSOC, for example. If consts were not used, you'd end up typing something like 35 (or whatever FETCH_ASSOC is defined as). This makes no sense to the reader.
An example of good define usage is maybe specifying your application's root path or a library's version number.
I know this is already answered, but none of the current answers make any mention of namespacing and how it affects constants and defines.
As of PHP 5.3, consts and defines are similar in most respects. There are still, however, some important differences:
Consts cannot be defined from an expression. const FOO = 4 * 3; doesn't work, but define('CONST', 4 * 3); does.
The name passed to define must include the namespace to be defined within that namespace.
The code below should illustrate the differences.
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
The content of the user sub-array will be ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].
=== UPDATE ===
The upcoming PHP 5.6 will allow a bit more flexibility with const. You will now be able to define consts in terms of expressions, provided that those expressions are made up of other consts or of literals. This means the following should be valid as of 5.6:
const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;
You still won't be able to define consts in terms of variables or function returns though, so
const RND = mt_rand();
const CONSTVAR = $var;
will still be out.
define I use for global constants.
const I use for class constants.
You cannot define into class scope, and with const you can.
Also, with const, it actually becomes a member of the class, and with define, it will be pushed to global scope.
I believe that as of PHP 5.3, you can use const outside of classes, as shown here in the second example:
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
NikiC's answer is the best, but let me add a non-obvious caveat when using namespaces so you don't get caught with unexpected behavior. The thing to remember is that defines are always in the global namespace unless you explicitly add the namespace as part of the define identifier. What isn't obvious about that is that the namespaced identifier trumps the global identifier. So :
<?php
namespace foo
{
// Note: when referenced in this file or namespace, the const masks the defined version
// this may not be what you want/expect
const BAR = 'cheers';
define('BAR', 'wonka');
printf("What kind of bar is a %s bar?\n", BAR);
// To get to the define in the global namespace you need to explicitely reference it
printf("What kind of bar is a %s bar?\n", \BAR);
}
namespace foo2
{
// But now in another namespace (like in the default) the same syntax calls up the
// the defined version!
printf("Willy %s\n", BAR);
printf("three %s\n", \foo\BAR);
}
?>
produces:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
Which to me makes the whole const notion needlessly confusing since the idea of a const in dozens of other languages is that it is always the same wherever you are in your code, and PHP doesn't really guarantee that.
Most of these answers are wrong or are only telling half the story.
You can scope your constants by using namespaces.
You can use the "const" keyword outside of class definitions. However, just like in
classes the values assigned using the "const" keyword must be
constant expressions.
For example:
const AWESOME = 'Bob'; // Valid
Bad example:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
To create variable constants use define() like so:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
To add on NikiC's answer. const can be used within classes in the following manner:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
You can not do this with define().
Yes, const are defined at compile-time and as nikic states cannot be assigned an expression, as define()'s can. But also const's cannot be conditionally declared (for the same reason). ie. You cannot do this:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
Whereas you could with a define(). So, it doesn't really come down to personal preference, there is a correct and a wrong way to use both.
As an aside... I would like to see some kind of class const that can be assigned an expression, a sort of define() that can be isolated to classes?
In one of my projects we are having a function which validates objects like:
if( true == valObj( $someObj, 'SomeClass' ) ) {
//Do some work;
}
While using this I thought this can be written like:
if( true == valObj( $someObj, SomeClass::class ) ) {
//Do some work;
}
Now I just want to know which approach is better and why?
Or are they same?
The ::class notation is generally better as it allows for easier usage finding and thereby refactoring: If you use an IDE like PHPStorm you can easily rename a class, and it will find and update all usages of OldClassName::class to NewClassname::class. This is not the case for the hardcoded string variant.
If you use namespaces using this notation can also result in less inline characters.
If you are running a PHP version that supports this notation, use it :)
SomeClass::class returns the full namespace including the class name.
Whilst if you use the string notation you have to add the namepace (if any) yourself.
Edit:
It doesn't matter which notation you choose, although I personally prefer the string notation as it shows you directly what namespace the class is in while scrolling through code.
from php.net
The special ::class constant are available as of PHP 5.5.0, and allows for fully qualified class name resolution at compile, this is useful for namespaced classes.
<?php
namespace foo {
class bar {
}
echo bar::class; // foo\bar
}
?>
This is also a magic constant. have a look at http://php.net/manual/en/language.constants.predefined.php
In PHP, you can declare constants in two ways:
With define keyword
define('FOO', 1);
Using const keyword
const FOO = 1;
What are the main differences between those two?
When and why should you use one and when use the other?
As of PHP 5.3 there are two ways to define constants: Either using the const keyword or using the define() function:
const FOO = 'BAR';
define('FOO', 'BAR');
The fundamental difference between those two ways is that const defines constants at compile time, whereas define defines them at run time. This causes most of const's disadvantages. Some disadvantages of const are:
const cannot be used to conditionally define constants. To define a global constant, it has to be used in the outermost scope:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
Why would you want to do that anyway? One common application is to check whether the constant is already defined:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const accepts a static scalar (number, string or other constant like true, false, null, __FILE__), whereas define() takes any expression. Since PHP 5.6 constant expressions are allowed in const as well:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const takes a plain constant name, whereas define() accepts any expression as name. This allows to do things like this:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
consts are always case sensitive, whereas define() allows you to define case insensitive constants by passing true as the third argument (Note: defining case-insensitive constants is deprecated as of PHP 7.3.0 and removed since PHP 8.0.0):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
So, that was the bad side of things. Now let's look at the reason why I personally always use const unless one of the above situations occurs:
const simply reads nicer. It's a language construct instead of a function and also is consistent with how you define constants in classes.
const, being a language construct, can be statically analysed by automated tooling.
const defines a constant in the current namespace, while define() has to be passed the full namespace name:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However, arrays will be supported for both cases in PHP 7.
const FOO = [1, 2, 3]; // Valid in PHP 5.6
define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0
Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Summary
Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!
Until PHP 5.3, const could not be used in the global scope. You could only use this from within a class. This should be used when you want to set some kind of constant option or setting that pertains to that class. Or maybe you want to create some kind of enum.
define can be used for the same purpose, but it can only be used in the global scope. It should only be used for global settings that affect the entire application.
An example of good const usage is to get rid of magic numbers. Take a look at PDO's constants. When you need to specify a fetch type, you would type PDO::FETCH_ASSOC, for example. If consts were not used, you'd end up typing something like 35 (or whatever FETCH_ASSOC is defined as). This makes no sense to the reader.
An example of good define usage is maybe specifying your application's root path or a library's version number.
I know this is already answered, but none of the current answers make any mention of namespacing and how it affects constants and defines.
As of PHP 5.3, consts and defines are similar in most respects. There are still, however, some important differences:
Consts cannot be defined from an expression. const FOO = 4 * 3; doesn't work, but define('CONST', 4 * 3); does.
The name passed to define must include the namespace to be defined within that namespace.
The code below should illustrate the differences.
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
The content of the user sub-array will be ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].
=== UPDATE ===
The upcoming PHP 5.6 will allow a bit more flexibility with const. You will now be able to define consts in terms of expressions, provided that those expressions are made up of other consts or of literals. This means the following should be valid as of 5.6:
const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;
You still won't be able to define consts in terms of variables or function returns though, so
const RND = mt_rand();
const CONSTVAR = $var;
will still be out.
define I use for global constants.
const I use for class constants.
You cannot define into class scope, and with const you can.
Also, with const, it actually becomes a member of the class, and with define, it will be pushed to global scope.
I believe that as of PHP 5.3, you can use const outside of classes, as shown here in the second example:
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
NikiC's answer is the best, but let me add a non-obvious caveat when using namespaces so you don't get caught with unexpected behavior. The thing to remember is that defines are always in the global namespace unless you explicitly add the namespace as part of the define identifier. What isn't obvious about that is that the namespaced identifier trumps the global identifier. So :
<?php
namespace foo
{
// Note: when referenced in this file or namespace, the const masks the defined version
// this may not be what you want/expect
const BAR = 'cheers';
define('BAR', 'wonka');
printf("What kind of bar is a %s bar?\n", BAR);
// To get to the define in the global namespace you need to explicitely reference it
printf("What kind of bar is a %s bar?\n", \BAR);
}
namespace foo2
{
// But now in another namespace (like in the default) the same syntax calls up the
// the defined version!
printf("Willy %s\n", BAR);
printf("three %s\n", \foo\BAR);
}
?>
produces:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
Which to me makes the whole const notion needlessly confusing since the idea of a const in dozens of other languages is that it is always the same wherever you are in your code, and PHP doesn't really guarantee that.
Most of these answers are wrong or are only telling half the story.
You can scope your constants by using namespaces.
You can use the "const" keyword outside of class definitions. However, just like in
classes the values assigned using the "const" keyword must be
constant expressions.
For example:
const AWESOME = 'Bob'; // Valid
Bad example:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
To create variable constants use define() like so:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
To add on NikiC's answer. const can be used within classes in the following manner:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
You can not do this with define().
Yes, const are defined at compile-time and as nikic states cannot be assigned an expression, as define()'s can. But also const's cannot be conditionally declared (for the same reason). ie. You cannot do this:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
Whereas you could with a define(). So, it doesn't really come down to personal preference, there is a correct and a wrong way to use both.
As an aside... I would like to see some kind of class const that can be assigned an expression, a sort of define() that can be isolated to classes?