非常简单的问题:在PHP中,何时使用
define('FOO', 1);
什么时候使用
const FOO = 1;
这两者之间的主要区别是什么?
答案 0 :(得分:984)
从PHP 5.3开始,define constants有两种方式:使用const
关键字或使用define()
函数:
const FOO = 'BAR';
define('FOO', 'BAR');
这两种方式的根本区别在于const
在编译时定义常量,而define
在运行时定义它们。这导致了大多数const
的缺点。 const
的一些缺点是:
const
不能用于有条件地定义常量。要定义全局常量,必须在最外层范围内使用它:
if (...) {
const FOO = 'BAR'; // invalid
}
// but
if (...) {
define('FOO', 'BAR'); // valid
}
为什么你要这样做呢?一个常见的应用是检查是否已定义常量:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const
接受静态标量(数字,字符串或其他常量,如true
,false
,null
,__FILE__
),而{ {1}}采用任何表达方式。由于PHP define()
中也允许使用PHP 5.6常量表达式:
const
const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously
define('BIT_5', 1 << 5); // always valid
采用普通常量名称,而const
接受任何表达式作为名称。这允许做这样的事情:
define()
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
始终区分大小写,而const
允许您通过传递define()
作为第三个参数来定义不区分大小写的常量:
true
所以,那是事情的坏方面。现在让我们看看为什么我个人总是使用define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
,除非出现上述情况之一:
const
只是阅读更好。它是一种语言结构而不是函数,也与您在类中定义常量的方式一致。const
可以通过自动化工具进行静态分析。 const
在当前命名空间中定义一个常量,而const
必须传递完整的命名空间名称:
define()
由于PHP 5.6 namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
常量也可以是数组,而const
尚不支持数组。但是,PHP 7中的两种情况都支持数组。
define()
最后,请注意,const FOO = [1, 2, 3]; // valid in PHP 5.6
define('FOO', [1, 2, 3]); // invalid in PHP 5.6, valid in PHP 7.0
也可以在类或接口中用于定义class constant或接口常量。 const
不能用于此目的:
define
<强>摘要强>
除非您需要任何类型的条件或表达定义,否则请使用class Foo {
const BAR = 2; // valid
}
// but
class Baz {
define('QUX', 2); // invalid
}
而不是const
s - 只是为了便于阅读!
答案 1 :(得分:195)
在PHP 5.3之前,const
无法在全局范围内使用。你只能在课堂上使用它。当您想要设置某种常量选项或与该类相关的设置时,应该使用此选项。或许你想创造某种枚举。
define
可用于相同目的,但只能在全局范围内使用。它只应用于影响整个应用程序的全局设置。
良好const
用法的一个例子是摆脱魔法数字。看看PDO's constants。例如,当您需要指定获取类型时,可以键入PDO::FETCH_ASSOC
。如果未使用consts,您最终会输入类似35
(或FETCH_ASSOC
定义的内容)的内容。这对读者没有意义。
良好define
用法的一个示例可能是指定应用程序的根路径或库的版本号。
答案 2 :(得分:36)
我知道这已经得到了解答,但目前的答案都没有提到命名空间以及它如何影响常量和定义。
从PHP 5.3开始,consts和define在大多数方面都是类似的。但是,仍然存在一些重要的差异:
const FOO = 4 * 3;
不起作用,但define('CONST', 4 * 3);
会起作用。 define
的名称必须包含要在该命名空间中定义的名称空间。下面的代码应说明不同之处。
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
用户子阵列的内容为['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]
。
===更新===
即将推出的PHP 5.6将为const
提供更多灵活性。现在,您可以根据表达式定义consts,前提是这些表达式由其他consts或文字组成。这意味着以下内容从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;
你仍然无法用变量或函数返回来定义consts,所以
const RND = mt_rand();
const CONSTVAR = $var;
仍然会出局。
答案 3 :(得分:22)
我相信从PHP 5.3开始,你可以在类之外使用const
,如第二个例子所示:
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
答案 4 :(得分:19)
define
我用于全局常量。
const
我用于类常量。
您不能define
进入班级范围,而const
则可以。
不用说,你不能在课堂范围之外使用const
此外,对于const
,它实际上成为了类的成员,define
,它将被推送到全局范围。
答案 5 :(得分:15)
NikiC的答案是最好的,但是在使用命名空间时让我添加一个非显而易见的警告,这样你就不会遇到意想不到的行为。要记住的是,除非您明确地将命名空间添加为定义标识符的一部分,否则定义在全局命名空间中始终。不明显的是,命名空间标识符胜过全局标识符。所以:
<?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);
}
?>
产生
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
对我来说,整个const概念不必要地混淆,因为在许多其他语言中使用const的想法是,无论你在代码中的哪个地方,它总是一样的,并且PHP并不能真正保证这一点。
答案 6 :(得分:11)
这些答案中的大多数都是错误的,或只讲述了一半的故事。
例如:
const AWESOME = 'Bob'; // Valid
错误的例子:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
要创建变量常量,请使用define(),如下所示:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
答案 7 :(得分:5)
是的,const是在编译时定义的,因为nikic状态不能像define()那样分配表达式。但是const也不能有条件地宣布(出于同样的原因)。即。你不能这样做:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
您可以使用define()。因此,它并没有真正归结为个人偏好,使用两者都有正确和错误的方式。
顺便说一句......我希望看到某种类const可以分配一个表达式,一种可以与类隔离的define()?
答案 8 :(得分:5)
添加NikiC的答案。 const
可以通过以下方式在类中使用:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
您无法使用define()
执行此操作。
答案 9 :(得分:3)
没有人说过关于php-doc的任何内容,但对我而言,const
的偏好也是一个非常重要的论据:
/**
* My foo-bar const
* @var string
*/
const FOO = 'BAR';
答案 10 :(得分:1)
使用define关键字constant,您将获得大小写的便利性
不敏感,但使用const关键字却没有。
define("FOO", 1,true);
echo foo;//1
echo "<br/>";
echo FOO;//1
echo "<br/>";
class A{
const FOO = 1;
}
echo A::FOO;//valid
echo "<br/>";
//but
class B{
define FOO = 1;//syntax error, unexpected 'define'
}
echo B::FOO;//invalid