define()vs const

dan*_*vis 643 php const constants

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

define('FOO', 1);
Run Code Online (Sandbox Code Playgroud)

你什么时候用的

const FOO = 1;
Run Code Online (Sandbox Code Playgroud)

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

Nik*_*kiC 1016

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

const FOO = 'BAR';
define('FOO', 'BAR');
Run Code Online (Sandbox Code Playgroud)

这两种方式之间的根本区别在于const在编译时定义常量,而define在运行时定义它们.这导致了大多数const的缺点.一些缺点const是:

  • const不能用于有条件地定义常量.要定义全局常量,必须在最外层范围内使用它:

    if (...) {
        const FOO = 'BAR';    // Invalid
    }
    // but
    if (...) {
        define('FOO', 'BAR'); // Valid
    }
    
    Run Code Online (Sandbox Code Playgroud)

    你为什么要这样做呢?一个常见的应用是检查是否已定义常量:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 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
    
    Run Code Online (Sandbox Code Playgroud)
  • const采用普通的常量名称,而define()接受任何表达式作为名称.这允许做这样的事情:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • consts始终区分大小写,而define()允许您通过传递true第三个参数来定义不区分大小写的常量:

    define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR
    
    Run Code Online (Sandbox Code Playgroud)

所以,这是事情的坏方面.现在让我们看一下我个人总是使用的原因,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');
    
    Run Code Online (Sandbox Code Playgroud)
  • 由于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
    
    Run Code Online (Sandbox Code Playgroud)

最后,请注意,const也可以在类或接口中使用它来定义类常量或接口常量.define不能用于此目的:

class Foo {
    const BAR = 2; // Valid
}
// But
class Baz {
    define('QUX', 2); // Invalid
}
Run Code Online (Sandbox Code Playgroud)

摘要

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

  • 使用`const`的另一个好处是缺少引号,这意味着它的格式与IDE中使用的格式相同. (6认同)
  • 这应该是 PHP 文档中的内容。这是我见过的最好的解释,尤其是大多数人忘记的部分(编译与运行时)。 (6认同)
  • `define('a',$ _GET ['param']);`,`const b = a;`完美地运行并获取值,而`const c = $ _GET ['param'];`无效.是`const`真的是编译时间吗?我几乎不这么认为......(在PHP 7.0.7上测试过) (3认同)
  • 据我所知,在 PHP 5.6 中,即使使用“const”语言构造,您也可以使用简单的标量表达式 - 请参阅 https://wiki.php.net/rfc/const_scalar_exprs (2认同)
  • https://wiki.php.net/rfc/case_insensitive_constant_deprecation “_在 PHP 8.0 中:删除声明不区分大小写常量的可能性。_”对于任何其他在区分大小写方面冒险进入未来的人 (2认同)

rye*_*guy 196

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

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

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

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

  • 还应该注意,PHP5.3可以在全局范围内使用const. (31认同)
  • 值得一提的是`const`与命名空间的使用. (12认同)

Gor*_*onM 37

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

从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));
}
Run Code Online (Sandbox Code Playgroud)

用户子阵列的内容将是['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;
Run Code Online (Sandbox Code Playgroud)

但是,您仍然无法根据变量或函数返回来定义consts

const RND = mt_rand();
const CONSTVAR = $var;
Run Code Online (Sandbox Code Playgroud)

仍然会出局.

  • "六点九?四十二?我总是说宇宙存在根本性的错误"如果你需要一个完整的解释,请查看道格拉斯亚当斯的作品. (9认同)
  • 我忍不住问:你是否有意识地将'FORTY_TWO`定义为54? (8认同)
  • 哦.我知道42岁是答案生命,宇宙,以及一切,但我错过了六点九分.感谢您的解释! (2认同)

小智 22

我相信从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;
?>
Run Code Online (Sandbox Code Playgroud)


Jac*_*kin 20

define 我用于全局常量.

const 我用于类常量.

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

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

  • 如其他答案中所述,const可以在PHP 5.3+的类之外使用 (7认同)

sla*_*ast 16

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);  
}
?>
Run Code Online (Sandbox Code Playgroud)

生产:

What kind of bar is a cheers bar? 
What kind of bar is a wonka bar?
willy wonka 
three cheers
Run Code Online (Sandbox Code Playgroud)

对我来说,整个const概念不必要地令人困惑,因为在许多其他语言中使用const的想法是,无论你在代码中的哪个地方,它总是一样的,并且PHP并不能保证这一点.

  • 是的,但是 `BAR` 和 `\foo\BAR` 只是*不*相同的常量。我同意这确实令人困惑,但如果您还考虑到命名空间逻辑以这种方式保持一致,并且 `const` 和 `define()` 都不像 C *宏* (`#define`),那么 PHP 可以有一些借口。 (2认同)
  • const 概念*正是*它应该表现的方式——你在一个命名空间中!你想要它没有命名空间标识符,然后在命名空间之外创建它。这也使它与在类中定义的 const 一致,即使它使用不同的语法。是的,define 也是一致的,但方式不同。 (2认同)

Awe*_*X64 12

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

  1. 您可以使用命名空间来限定常量.
  2. 您可以在类定义之外使用"const"关键字.但是,就像在类中一样,使用"const"关键字赋值的值必须是常量表达式.

例如:

const AWESOME = 'Bob'; // Valid
Run Code Online (Sandbox Code Playgroud)

不好的例子:

const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic) 
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
Run Code Online (Sandbox Code Playgroud)

要创建变量常量,请使用define(),如下所示:

define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
Run Code Online (Sandbox Code Playgroud)

  • PHP 7可以使用```const WEAKNESS = 4 + 5 + 6;``` (3认同)
  • PHP &gt;=5.6 Zend Engine Compiler 中进行了一些更改,并且 const 现在以另一种方式处理。 (2认同)

MrW*_*ite 6

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

if (/* some condition */) {
  const WHIZZ = true;  // CANNOT DO THIS!
}
Run Code Online (Sandbox Code Playgroud)

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

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


Mar*_*ind 5

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

class Foo {
    const BAR = 1;

    public function myMethod() {
        return self::BAR;
    }
}
Run Code Online (Sandbox Code Playgroud)

你不能这样做define().