在 PHP 中,您可以通过两种方式声明常量:
使用定义关键字define('FOO', 1);使用 const 关键字 const FOO = 1;
这两者之间的主要区别是什么?
何时以及为什么要使用其中一种,何时使用另一种?
const
比 define
快两倍。关于页面加载时间和内存使用情况:请参阅 this question 和 this article...另请参阅有关操作码缓存 here 的内容。
自 PHP 5.3 起,define constants 有两种方法:使用 const
关键字或使用 define()
函数:
const FOO = 'BAR';
define('FOO', 'BAR');
这两种方式的根本区别在于 const
在编译时定义常量,而 define
在运行时定义它们。这导致了 const
的大部分缺点。 const
的一些缺点是:
const 不能用于有条件地定义常量。要定义全局常量,必须在最外层范围内使用它: if (...) { const FOO = 'BAR'; // 无效 } // 但是 if (...) { define('FOO', 'BAR'); // 有效 } 你为什么要这样做呢?一种常见的应用是检查常量是否已经定义: if (!defined('FOO')) { define('FOO', 'BAR'); }
const 接受静态标量(数字、字符串或其他常量,如 true、false、null、__FILE__),而 define() 接受任何表达式。由于 PHP 5.6 的常量表达式也允许在 const 中使用: const BIT_5 = 1 << 5; // 自 PHP 5.6 起有效,之前无效 define('BIT_5', 1 << 5); // 始终有效
const 接受一个普通的常量名称,而 define() 接受任何表达式作为名称。这允许做这样的事情: for ($i = 0; $i < 32; ++$i) { define('BIT_' . $i, 1 << $i); }
const 始终区分大小写,而 define() 允许您通过将 true 作为第三个参数传递来定义不区分大小写的常量(注意:定义不区分大小写的常量自 PHP 7.3.0 起已弃用,自 PHP 8.0.0 起已删除):define ('FOO','BAR',真);回声FOO; // BAR 回声 foo; // 酒吧
所以,这是事情不好的一面。现在让我们看看我个人总是使用 const
的原因,除非出现上述情况之一:
const 只是读起来更好。它是一种语言构造而不是函数,并且与您在类中定义常量的方式一致。
const 作为一种语言结构,可以通过自动化工具进行静态分析。
const 在当前命名空间中定义一个常量,而 define() 必须传递完整的命名空间名称:命名空间 A\B\C; // 定义常量 A\B\C\FOO: const FOO = 'BAR';定义('A\B\C\FOO', 'BAR');
由于 PHP 5.6 const 常量也可以是数组,而 define() 还不支持数组。但是,在 PHP 7 中这两种情况都支持数组。 const FOO = [1, 2, 3]; // 在 PHP 5.6 中有效 define('FOO', [1, 2, 3]); // 在 PHP 5.6 中无效,在 PHP 7.0 中有效
最后,请注意 const
也可以在类或接口中用于定义 class constant 或接口常量。 define
不能用于此目的:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
概括
除非您需要任何类型的条件或表达式定义,否则请使用 const
而不是 define()
- 只是为了便于阅读!
在 PHP 5.3 之前,const
不能在全局范围内使用。你只能在课堂上使用它。当您想要设置某种常量选项或与该类相关的设置时,应该使用它。或者,也许您想创建某种枚举。
define
可用于相同目的,但只能在全局范围内使用。它应该只用于影响整个应用程序的全局设置。
一个好的 const
用法示例是去掉幻数。看看PDO's constants。例如,当您需要指定提取类型时,您可以输入 PDO::FETCH_ASSOC
。如果不使用 const,您最终会输入类似 35
的内容(或任何 FETCH_ASSOC
定义的内容)。这对读者来说毫无意义。
一个好的 define
用法示例可能是指定应用程序的根路径或库的版本号。
const
与命名空间一起使用可能值得一提。
我知道这已经得到解答,但是当前的答案都没有提到命名空间以及它如何影响常量和定义。
自 PHP 5.3 起,const 和定义在大多数方面都相似。但是,仍然存在一些重要的区别:
不能从表达式定义常量。常量 FOO = 4 * 3;不起作用,但定义('CONST', 4 * 3);做。
传递给定义的名称必须包括要在该命名空间中定义的命名空间。
下面的代码应该说明这些差异。
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
提供更多的灵活性。您现在可以根据表达式定义 const,前提是这些表达式由其他 const 或文字组成。这意味着以下内容应从 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;
但是,您仍然无法根据变量或函数返回来定义 const,所以
const RND = mt_rand();
const CONSTVAR = $var;
仍然会出来。
FORTY_TWO
定义为 54 吗?
define
我用于全局常量。
const
我用于类常量。
您不能 define
进入类范围,而使用 const
可以。
此外,使用 const
,它实际上成为类的成员,而使用 define
,它将被推送到全局范围。
我相信从 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;
?>
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 并不能真正保证这一点。
BAR
和 \foo\BAR
只是 不 相同的常量。我同意这确实令人困惑,但是如果您还认为命名空间逻辑这样的事情是一致的,并且 const
和 define()
都不像 C macro (#define
),那么PHP可以有一些借口。
这些答案中的大多数都是错误的,或者只说明了一半。
您可以使用命名空间来确定常量的范围。您可以在类定义之外使用“const”关键字。但是,就像在类中一样,使用“const”关键字分配的值必须是常量表达式。
例如:
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
是的,const 是在编译时定义的,因为不能为 nikic 状态分配表达式,而 define() 可以。但也不能有条件地声明 const(出于同样的原因)。 IE。你不能做这个:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
而你可以使用define()。因此,它并没有真正归结为个人喜好,两者都有正确和错误的使用方式。
顺便说一句......我想看到某种可以分配表达式的类 const,一种可以隔离到类的 define() ?
添加 NikiC 的答案。 const
可以通过以下方式在类中使用:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
您不能使用 define()
执行此操作。
const
语言结构,您也可以使用简单的标量表达式 - 请参阅 wiki.php.net/rfc/const_scalar_exprsconst
的另一个好处是没有引号,这意味着它的格式与在 IDE 中使用的相同。define('a', $_GET['param']);
、const b = a;
完美运行并获取值,而const c = $_GET['param'];
无效。const
真的是编译时间吗?我几乎不这么认为......(在 PHP 7.0.7 上测试)