define()与const

很直截了当的问题:在PHP中,你什么时候使用

define('FOO', 1); 

你什么时候用

 const FOO = 1; 

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

从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接受一个静态标量(数字,string或其他常数,如truefalsenull__FILE__ ),而define()则使用任何expression式。 由于常量expression式允许使用PHP 5.6常量expression式,

     const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously define('BIT_5', 1 << 5); // always valid 
  • const接受一个普通的常量名,而define()接受任何expression式作为名字。 这允许做这样的事情:

     for ($i = 0; $i < 32; ++$i) { define('BIT_' . $i, 1 << $i); } 
  • const总是区分大小写的,而define()允许你通过传递true作为第三个参数来定义不区分大小写的常量:

     define('FOO', 'BAR', true); echo FOO; // BAR echo foo; // BAR 

所以,这是事情的坏处。 现在让我们看看为什么我个人总是使用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()要快一些。

    众所周知,当使用大量的常量时,PHP define()很慢。 人们甚至发明了像apc_load_constants()hidef来解决这个问题。

    const使得const的定义大约快一倍(在XDebug打开的开发机器上)。 查询时间另一方面不会改变(因为两个常量types共享相同的查找表): 演示 。

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

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

概要

除非需要任何types的条件或expression式定义,否则使用const s而不是define() s – 仅仅是为了便于阅读!

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

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

一个很好的const用法的例子是摆脱幻数。 看看PDO的常量 。 当您需要指定提取types时,例如,您将键入PDO::FETCH_ASSOC 。 如果不使用const,你最终会input35 (或者其他的FETCH_ASSOC被定义为)。 这对读者来说没有意义。

一个好的define用法的例子可能是指定你的应用程序的根path或一个库的版本号。

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

从PHP 5.3开始,常量和定义在大多数方面是相似的。 但是,还是有一些重要的区别:

  • Consts不能从expression式中定义。 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有更多的灵活性。 你现在可以用expression式来定义const,只要这些expression式是由其他常量或文字组成的。 这意味着以下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; 

尽pipe如此,你仍然无法通过variables或函数返回来定义const

 const RND = mt_rand(); const CONSTVAR = $var; 

仍然会出局。

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

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的概念总是和代码中的任何地方一样,而PHP并不能保证这一点。

这些答案大部分是错误的,或者只是讲述了一半的故事。

  1. 你可以使用命名空间来限定你的常量。
  2. 您可以在类定义之外使用“const”关键字。 但是,就像在类中一样,使用“const”关键字指定的值必须是常量expression式。

例如:

 const AWESOME = 'Bob'; // Valid 

不好的例子:

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

要创buildvariables常量使用define()就像这样:

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

是的,const是在编译时定义的,而nikic状态是不能被赋值的,就像define()的can一样。 但是也不能有条件地声明const(出于同样的原因)。 即。 你不可以做这个:

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

而你可以用define()。 所以,这并不是真正归因于个人喜好,使用两者的方法是正确的和错误的。

作为一个旁白…我想看到某种types的const可以被分配一个expression式,一种可以被隔离到类的define()?

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

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

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