提问



非常直截了当的问题:在PHP中,你何时使用


define('FOO', 1);


你什么时候用的


const FOO = 1;


这两者之间的主要区别是什么?

最佳参考


从PHP 5.3开始,有两种方法可以定义常量:使用const关键字或使用define()函数:[77] [78]


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接受静态标量(数字,字符串或其他常数,如truefalsenull__FILE__),而define()采取任何表达方式。由于const中允许使用PHP 5.6常量表达式:


    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 s始终区分大小写,而define()允许您通过传递true作为第三个参数来定义不区分大小写的常量:


    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, valid in PHP 7.0
    



最后,请注意const也可以在类或接口中用于定义类常量或接口常量。 define不能用于此目的:[79]


class Foo {
    const BAR = 2; // valid
}
// but
class Baz {
    define('QUX', 2); // invalid
}


摘要


除非你需要任何类型的条件或表达定义,否则使用const而不是define() s - 只是为了便于阅读!

其它参考1


在PHP 5.3之前,const不能在全球范围内使用。你只能在课堂上使用它。当您想要设置某种常量选项或与该类相关的设置时,应该使用此选项。或许你想创造某种枚举。


define可用于相同目的,但它只能用于全局范围。它应该仅用于影响整个应用程序的全局设置。


良好const用法的一个例子是摆脱魔法数字。看看PDO的常量。当你需要指定一个获取类型时,你可以输入PDO::FETCH_ASSOC。如果没有使用consts,你最终会输入像35这样的东西(或者FETCH_ASSOC被定义为)。这对读者没有意义。[80]


良好define用法的一个例子是指定应用程序的根路径或库的版本号。

其它参考2


我知道这已经得到了解答,但目前的答案都没有提到命名空间以及它如何影响常量和定义。


从PHP 5.3开始,consts和define在大多数方面都是类似的。但是,仍然存在一些重要的差异:



  • 无法从表达式定义Consts。 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


我相信从PHP 5.3开始,你可以在类之外使用const,如第二个例子所示:


http://www.php.net/manual/en/language.constants.syntax.php[81]


<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';

echo CONSTANT;
?>

其它参考4


define我用于全局常量。


const我用于类常量。


你不能define进入班级范围,你可以用const
不用说,你不能使用const外部范围


此外,使用const,它实际上成为类的成员,define,它将被推到全局范围。

其它参考5


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


大多数这些答案都是错误的,或只讲述了一半的故事。



  1. 您可以使用命名空间来限定常量。

  2. 您可以在类定义之外使用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

其它参考7


是的,const是在编译时定义的,因为nikic状态不能分配一个表达式,因为define()可以。但是const也不能有条件地声明(出于同样的原因)。即。你不可以做这个:


if (/* some condition */) {
  const WHIZZ = true;  // CANNOT DO THIS!
}


而你可以使用define()。因此,它并没有真正归结为个人偏好,使用两者都有正确和错误的方法。


顺便说一句......我想看到某种类const可以分配一个表达式,一种可以与类隔离的define()?

其它参考8


添加NikiC的答案。const可以通过以下方式在类中使用:


class Foo {
    const BAR = 1;

    public function myMethod() {
        return self::BAR;
    }
}


你不能用define()做到这一点。

其它参考9


没有人说过关于php-doc的任何内容,但对我而言,这也是const偏好的一个非常重要的论据:


/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';