在PHP中,何时使用
define('FOO', 1);
以及何时使用
const FOO = 1;
?
两者之间的主要区别是什么?
在PHP中,何时使用
define('FOO', 1);
以及何时使用
const FOO = 1;
?
两者之间的主要区别是什么?
Answers:
从PHP 5.3开始,有两种定义常量的方法:使用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__
),而define()
采取的任何表达式。由于PHP 5.6也允许使用常量表达式const
:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const
采用简单的常量名称,而define()
接受任何表达式作为名称。这样可以执行以下操作:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
const
s始终区分大小写,而define()
允许您通过将其true
作为第三个参数传递来定义不区分大小写的常量(注意:自PHP 7.3.0起不建议使用不区分大小写的常量。):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
所以,那是不好的一面。现在,让我们看看const
除非出现以下情况之一,否则我个人始终使用的原因:
const
读起来更好。它是一种语言构造,而不是函数,并且与您在类中定义常量的方式一致。const
作为一种语言构造,可以通过自动化工具进行静态分析。const
在当前名称空间中定义一个常量,同时define()
必须传递完整的名称空间名称:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
由于PHP 5.6 const
常量也可以是数组,而define()
尚不支持数组。但是,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
最后,请注意,const
也可以在类或接口内使用它来定义类常量或接口常量。define
不能用于此目的:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
摘要
除非您需要任何类型的条件或表达式定义,否则使用const
s代替define()
s-仅出于可读性考虑!
const
语言结构,也可以使用简单的标量表达式-参见wiki.php.net/rfc/const_scalar_exprs
const
是缺少引号,这意味着它的格式与在IDE中使用的格式相同。
define('a', $_GET['param']);
,const b = a;
可以完美工作并在const c = $_GET['param'];
无效时获取值。const
真的是编译时间吗?我几乎不这么认为...(在PHP 7.0.7上测试)
直到PHP 5.3,const
才可以在全局范围内使用。您只能在一个班级中使用它。当您要设置某种与该类有关的常量选项或设置时,应使用此选项。或者,也许您想创建某种枚举。
define
可以出于相同的目的使用,但只能在全局范围内使用。仅应将其用于影响整个应用程序的全局设置。
良好const
用法的一个例子是摆脱魔术数字。看一下PDO的常量。例如,当您需要指定提取类型时,可以输入PDO::FETCH_ASSOC
。如果不使用const,您最终将输入类似35
(或FETCH_ASSOC
定义为)的内容。这对读者没有意义。
良好define
用法的一个示例是指定应用程序的根路径或库的版本号。
const
with与命名空间的使用。
我知道已经回答了这个问题,但是当前的回答都没有提及命名空间及其对常量和定义的影响。
从PHP 5.3开始,const和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
。现在,您将能够根据表达式定义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?
我相信从PHP 5.3开始,您可以const
在类外部使用,如第二个示例所示:
http://www.php.net/manual/zh/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
define
我用全局常量。
const
我使用类常量。
您不能define
进入课堂范围,而const
可以。不用说,您不能使用const
外部类作用域。
同样,使用const
,它实际上成为该类的成员,并且使用define
,它将被推到全局范围。
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 宏(#define
),那么PHP可以找些借口。
这些答案大多数都是错误的,或者只讲了一半。
例如:
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
没有人说过有关php-doc的任何信息,但对我来说,这也是首选参数const
:
/**
* My foo-bar const
* @var string
*/
const FOO = 'BAR';
使用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
const
比快两倍define
。关于页面加载时间和内存使用情况:请参见此问题和本文 ...另请参见此处有关操作码缓存的内容。