首页 文章

define()vs const

提问于
浏览
582

非常简单的问题:在PHP中,你什么时候使用

define('FOO', 1);

你什么时候用的

const FOO = 1;

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

10 回答

  • 12

    从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 接受静态标量(数字,字符串或其他常量,如 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 也可以在类或接口中用于定义class constant或接口常量 . define 不能用于此目的:

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

    Summary

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

  • 12

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

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

    好的_1223652用法的一个例子就是摆脱魔法数字 . 看看PDO's constants . 例如,当您需要指定获取类型时,可以键入 PDO::FETCH_ASSOC . 如果没有使用consts,你最终会输入类似 35 (或任何 FETCH_ASSOC 定义为)的内容 . 这对读者没有意义 .

    良好 define 用法的一个示例可能是指定您的应用程序's root path or a library'的版本号 .

  • 18

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

    从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] .

    === UPDATE ===

    即将推出的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;
    

    仍然会出局 .

  • 4

    我相信从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;
    ?>
    
  • 5

    define 我用于全局常量 .

    const 我用于类常量 .

    你不能 define 进入类范围,并且 const 你可以 . 不用说,你不能使用 const 外类范围

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

  • 943

    NikiC 's answer is the best, but let me add a non-obvious caveat when using namespaces so you don' t遇到意外行为 . 要记住的是,除非您明确地将命名空间添加为定义标识符的一部分,否则定义始终位于全局命名空间中 . 不明显的是,命名空间标识符胜过全局标识符 . 所以:

    <?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并不能保证这一点 .

  • 193

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

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

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

    是的,const是在编译时定义的,因为nikic状态不能像define()那样分配表达式 . 但是const也不能有条件地宣布(出于同样的原因) . 即 . 你不能做这个:

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

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

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

  • 35

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

    class Foo {
        const BAR = 1;
    
        public function myMethod() {
            return self::BAR;
        }
    }
    

    您无法使用 define() 执行此操作 .

  • 22

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

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

相关问题