PHP常量是否可以包含数组?

452

这个失败了:

 define('DEFAULT_ROLES', array('guy', 'development team'));

显然,常量不能存储数组。如何最好地解决这个问题?

define('DEFAULT_ROLES', 'guy|development team');

//...

$default = explode('|', DEFAULT_ROLES);

这似乎是不必要的努力。


22
PHP 5.6支持常量数组,请见下面我的回答。 - Andrea
1
当您需要将数组用作常量时,您是否正在尝试进行枚举?如果是这样,请使用SplEnum:http://php.net/manual/en/class.splenum.php - ziGi
2
@ziGi 今天遇到了这个问题,有不同类型的图像需要存储,需要特定的尺寸,将这些尺寸作为常量数组存储比分别存储宽度和高度更加有用。 - Matt K
17个回答

1007

自 PHP 5.6 起,您可以使用 const 声明一个数组常量:

<?php
const DEFAULT_ROLES = array('guy', 'development team');

短语法也可以正常工作,如你所预期:

<?php
const DEFAULT_ROLES = ['guy', 'development team'];

如果您使用的是 PHP 7,您终于可以像最初尝试时那样使用 define()

<?php
define('DEFAULT_ROLES', array('guy', 'development team'));

56
这个需要被点赞,因为其他回答已经过时或者只是由了解不全面的用户编写。 - Andreas Bergström
7
@JackNicholsonn 很遗憾,在 PHP 5.6 中你不能使用 define(),但是在 PHP 7.0 中已经修复了这个问题。 :) - Andrea
1
@AndreasBergström 不,这个问题太新了。这个问题是在2009年提出的!现在这种语法对大多数用户来说几乎没有用处。几乎所有人的服务器上都有PHP 5.6。其他答案也很好,因为它们还提供了替代方案。如果您不想使用类,则已接受的答案是迄今为止唯一可行的方法。 - Ismael Miguel
@IsmaelMiguel 不要太确定,因为并非所有人都有5.6版本。关于一个月前,任何在Windows服务器上的人最近都从Microsoft获取了5.6 SQL Server驱动程序。 - M H
因为这是原始问题所做的。 - Andrea
显示剩余6条评论

521

PHP 5.6+ 引入了 const 数组 - 请参见 Andrea Faulds 的答案

您还可以将数组序列化,然后将其放入常量中:

# define constant, serialize array
define ("FRUITS", serialize (array ("apple", "cherry", "banana")));

# use it
$my_fruits = unserialize (FRUITS);

23
这段代码虽然优雅但速度较慢。使用一个公共的静态类方法返回该数组会更好。 - noun
4
在这里加一条注释,即在PHP 5.6中,您现在可以拥有常量数组。 const fruits = ['apple','cherry','banana']; - Alex K

147

您可以将它们存储为类的静态变量:

class Constants {
    public static $array = array('guy', 'development team');
}
# Warning: array can be changed lateron, so this is not a real constant value:
Constants::$array[] = 'newValue';
如果您不喜欢数组会被他人更改的想法,可以使用getter方法:
class Constants {
    private static $array = array('guy', 'development team');
    public static function getArray() {
        return self::$array;
    }
}
$constantArray = Constants::getArray();

编辑

自从PHP5.4以来,甚至可以在不需要中间变量的情况下访问数组值,即以下方式是有效的:

$x = Constants::getArray()['index'];

1
+1. 我已经在做这个多年了:const AtomicValue =42; public static $fooArray = ('how','di') - Frank N
9
虽然我认为在php中不能创建不可变数组这一点很荒谬,但这提供了一个不错的解决方法。 - Akoi Meexx
如果您经常使用常量,我肯定会避免函数调用,因为它们非常昂贵。静态是正确的选择。 - Chris Seufert
1
这个解决方案比我预期的要棒得多:我只需要数组的一部分值,因此我在函数中使用了一些参数,而不是简单地获取整个数组。在我的情况下,Constants::getRelatedIDs($myID)会给我一个内部数组,其中只有我需要的值(我还在这个函数中进行了一些ID验证)。@cseufert 如果我获取整个数组并为每种情况过滤,那么对我来说将会更加昂贵... - Armfoot
1
拥有一个带有私有静态成员的函数(getArray)是常量的最佳表示,因为它们可以被更改。 - Kamaldeep singh Bhatia

41

我和你做的一样。所以我正在寻找性能优化,看看这是否好或者有更好的方法。 - Smile
我同意这个解决方案。因为它简单易懂。 - Faris Rayhan

12

这是我使用的方法。它与 soulmerge 提供的示例类似,但通过这种方式,您可以获取完整的数组或数组中的单个值。

class Constants {
    private static $array = array(0 => 'apple', 1 => 'orange');

    public static function getArray($index = false) {
        return $index !== false ? self::$array[$index] : self::$array;
    }
}

就这样使用:

Constants::getArray(); // Full array
// OR 
Constants::getArray(1); // Value of 1 which is 'orange'

10

PHP 7+

自 PHP 7 版本开始,你可以使用 define() 函数来定义一个常量数组:

define('ANIMALS', [
    'dog',
    'cat',
    'bird'
]);

echo ANIMALS[1]; // outputs "cat"

9

您可以将其存储为常量的JSON字符串。从应用程序的角度来看,JSON在其他情况下也可能很有用。

define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));    
$fruits = json_decode (FRUITS);    
var_dump($fruits);

这正是我所想的。这难道不是一个合理的好回答吗? - Con Antonakos
这在AngularJS中非常有效,因为它可以消耗JSON。我觉得这比序列化的答案好多了,但是序列化更好的原因是什么呢?也许更快吗? - Drellgor
是的,序列化技术上更快。然而,对于大多数情况下所需的小数据集,我更喜欢使用这种方法,因为它更安全。当您反序列化时,可能会执行代码。即使在这种情况下风险非常低,我认为我们应该仅在极端情况下才使用反序列化。 - Mario Awad

4

甚至可以与关联数组一起使用,例如在类中。

class Test {

    const 
        CAN = [
            "can bark", "can meow", "can fly"
        ],
        ANIMALS = [
            self::CAN[0] => "dog",
            self::CAN[1] => "cat",
            self::CAN[2] => "bird"
        ];

    static function noParameter() {
        return self::ANIMALS[self::CAN[0]];
    }

    static function withParameter($which, $animal) {
        return "who {$which}? a {$animal}.";
    }

}

echo Test::noParameter() . "s " . Test::CAN[0] . ".<br>";
echo Test::withParameter(
    array_keys(Test::ANIMALS)[2], Test::ANIMALS["can fly"]
);

// dogs can bark.
// who can fly? a bird.

4

我知道这是一个有点老的问题,但这是我的解决方案:

<?php
class Constant {

    private $data = [];

    public function define($constant, $value) {
        if (!isset($this->data[$constant])) {
            $this->data[$constant] = $value;
        } else {
            trigger_error("Cannot redefine constant $constant", E_USER_WARNING);
        }
    }

    public function __get($constant) {
        if (isset($this->data[$constant])) {
            return $this->data[$constant];
        } else {
            trigger_error("Use of undefined constant $constant - assumed '$constant'", E_USER_NOTICE);
            return $constant;
        }
    }

    public function __set($constant,$value) {
        $this->define($constant, $value);
    }

}
$const = new Constant;

我定义它是因为我需要在常量中存储对象和数组,所以我还安装了php的runkit,这样我就可以使$const变量成为超级全局变量。

你可以这样使用它:$const->define("my_constant",array("my","values")); 或者只需 $const->my_constant = array("my","values");

要获取值,只需简单地调用$const->my_constant;


哇,我没想到会有这样的方法...... 我甚至不知道 __get__set... 我必须承认这种方法很棒。 - user5147563
这些被称为魔术方法,请查看 PHP 文档了解更多信息。 - Rikudou_Sennin

4
如果您正在使用PHP 7及以上版本,您也可以像这样使用fetch。
define('TEAM', ['guy', 'development team']);
echo TEAM[0]; 
// output from system will be "guy"

1
这与2年前发布的此答案完全相同。 - Walf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接