define() vs const
非常简单的问题:在PHP中,您何时使用
1 |
你什么时候用
1 | const FOO = 1; |
这两者的主要区别是什么?
从php5.3开始,定义常量有两种方法:使用
1 2 |
这两种方法的根本区别在于
const 不能用于有条件地定义常量。要定义全局常量,必须在最外部的作用域中使用它:1
2
3
4
5
6
7你为什么要这样做?一个常见的应用程序是检查常量是否已定义:
const 接受静态标量(数字、字符串或其他常数,如true 、false 、null 、__FILE__ ,而define() 接受任何表达式。由于const 中也允许使用php5.6常量表达式:1
2const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously
define('BIT_5', 1 << 5); // always validconst 采用纯常量名,而define() 接受任何表达式作为名称。这样做可以做到:1
2
3const s总是区分大小写,而define() 允许您通过将true 作为第三个参数来定义不区分大小写的常量:1
2
3
所以,这是坏的一面。现在让我们来看看为什么我个人总是使用
const 读起来更清楚。它是一种语言构造,而不是函数,并且与您在类中定义常量的方式一致。const 是一种语言结构,可以通过自动化工具进行静态分析。const 在当前命名空间中定义了一个常量,而define() 必须传递完整的命名空间名称:1
2
3
4namespace 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中,两种情况都支持数组。1
2const FOO = [1, 2, 3]; // valid in PHP 5.6
define('FOO', [1, 2, 3]); // invalid in PHP 5.6, valid in PHP 7.0
最后,请注意,
1 2 3 4 5 6 7 |
总结
除非您需要任何类型的条件定义或表达定义,否则使用
在php5.3之前,
很好的
良好的
我知道这已经被回答了,但是目前的答案都没有提到名称间距以及它如何影响常量和定义。
从php 5.3开始,consts和defines在大多数方面都是相似的。然而,仍然存在一些重要的差异:
- 不能从表达式定义常量。
const FOO = 4 * 3; 不起作用,但define('CONST', 4 * 3); 起作用。 - 传递给
define 的名称必须包括要在该名称空间中定义的名称空间。
下面的代码应该说明这些差异。
1 2 3 4 5 6 7 8 9 10 | namespace foo { const BAR = 1; define('BAZ', 2); define(__NAMESPACE__ . '\\BAZ', 3); } namespace { var_dump(get_defined_constants(true)); } |
用户子数组的内容将是
===更新===
即将推出的php 5.6将使
1 2 3 | 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; |
但是,您仍然无法根据变量或函数返回定义常量,因此
1 2 |
仍将外出。
我相信从php5.3开始,您可以在类外使用
http://www.php.net/manual/en/language.constants.syntax.php
我用
我用
您不能将
另外,在
Nikic的回答是最好的,但是让我在使用名称空间时添加一个不明显的警告,这样您就不会被意外行为捕获。要记住的是,除非将命名空间显式添加为define标识符的一部分,否则定义始终位于全局命名空间中。不明显的是,名称空间标识符胜过全局标识符。所以:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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? ", 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? ", \BAR); } namespace foo2 { // But now in another namespace (like in the default) the same syntax calls up the // the defined version! printf("Willy %s ", BAR); printf("three %s ", \foo\BAR); } ?> |
生产:
1 2 3 4 | What kind of bar is a cheers bar? What kind of bar is a wonka bar? willy wonka three cheers |
对我来说,这使得整个const概念不必要地令人困惑,因为在许多其他语言中,const的概念是,在代码中的任何位置都是相同的,而php并不能真正保证这一点。
这些答案大多是错误的,或者只讲了一半。
例如:
1 | const AWESOME = 'Bob'; // Valid |
坏榜样:
1 2 3 | const AWESOME = whatIsMyName(); // Invalid (Function call) const WEAKNESS = 4+5+6; // Invalid (Arithmetic) const FOO = BAR . OF . SOAP; // Invalid (Concatenation) |
要创建变量常量,请使用define(),如下所示:
1 2 3 |
加上尼基的回答。
1 2 3 4 5 6 7 | class Foo { const BAR = 1; public function myMethod() { return self::BAR; } } |
你不能用
是的,const是在编译时定义的,由于nikic状态不能被分配表达式,因此define()可以。但const也不能有条件地声明(出于同样的原因)。也就是说,你不能这样做:
1 2 3 | if (/* some condition */) { const WHIZZ = true; // CANNOT DO THIS! } |
而您可以使用define()。所以,这并不取决于个人喜好,有一个正确和错误的方法来使用两者。
作为旁白…我想看看可以分配给表达式的类const,一种可以隔离到类的define()?
没有人提到php-doc,但对我来说,这也是一个非常重要的理由来支持
1 2 3 4 5 | /** * My foo-bar const * @var string */ const FOO = 'BAR'; |
使用define关键字常量,您将获得case的功能不敏感,但对于const关键字,您没有。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |