PHP常量包含数组?


407

这失败了:

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

显然,常量不能保存数组。解决此问题的最佳方法是什么?

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

//...

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

这似乎是不必要的努力。


17
PHP 5.6支持常量数组,请参见下面的答案。
Andrea

1
什么时候需要将数组用作常量,您是否要进行枚举?如果是这样,则使用SplEnum:php.net/manual/en/class.splenum.php
ziGi 2014年

2
@ziGi今天出现了此问题,具有不同类型的图像,需要特定的尺寸来存储,将这些尺寸存储为常量数组变得有用,而不是将一个尺寸存储为宽度和一个高度。
Matt K

Answers:


498

注意:虽然这是公认的答案,但值得注意的是,在PHP 5.6+中,您可以拥有const数组- 请参见下面的Andrea Faulds的答案

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

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

# use it
$my_fruits = unserialize (FRUITS);

40
只是想说我喜欢这个解决方案:)
GateKiller

16
真好 但是不好的一点是您不能以这种方式定义类常量。
格雷戈尔

19
最好坚持使用类中的静态变量。
尔根·保罗

5
太糟糕了,您不能做:$fruit = FRUITS[0];
Sophivorus

20
这段代码很优雅,但是速度很慢。最好使用返回数组的公共静态类方法。
名词

844

从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'));

41
由于所有其他答案都已过时或只是由错误的用户撰写的,因此需要对此进行投票。
AndreasBergström2014年

那是唯一的语法吗?您可以使用旧的define函数吗?define('ARRAY_CONSTANT',array('item1','item2','item3'));
2014年

5
@JackNicholsonn不幸的是,您不能define()在PHP 5.6中使用,但这已在PHP 7.0中修复。:)
Andrea

@AndreasBergström不,这个问题太新了。这个问题是2009年提出的!对于当今的大多数用户来说,这种语法几乎是无用的。几乎每个人的服务器上都装有PHP 5.6。其他答案也很好,因为它们也提供了替代方案。如果您不想使用类,那么可接受的答案是到目前为止唯一可行的方法。
Ismael Miguel 2015年

@IsmaelMiguel不能确保它们都具有5.6。大约一个月前,Windows服务器上的任何人现在都从Microsoft获得了5.6 sql服务器驱动程序。
MH 2015年

141

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

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';

如果您不喜欢其他人可以更改数组的想法,那么使用吸气剂可能会有所帮助:

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')
弗兰克·诺克

9
虽然我们无法在php中创建不可变数组对我来说似乎很可笑,但这提供了一个不错的解决方法。
Akoi Meexx 2012年

如果您经常使用常量,那么我肯定会避免函数调用,因为它们非常昂贵。静态是要走的路。
克里斯·塞弗特

1
此解决方案比我预期的要好得多:我只需要数组值的一部分,因此,我在函数中使用了一些参数,而不是简单地获取数组。在我的情况下,Constants :: getRelatedIDs($ myID)为我提供了一个仅包含所需值的内部数组(我还在此函数中进行了一些ID验证)。@cseufert获取整个阵列并针对每种情况进行过滤对我而言将更加昂贵……
Armfoot

1
具有私有静态成员函数(的getArray)是最好的表现为常数,因为他们可以改变👍🏻
Kamaldeep辛格·巴蒂亚

41

如果您使用的是PHP 5.6或更高版本,请使用Andrea Faulds答案

我正在这样使用它。希望对别人有帮助。

config.php

class app{
    private static $options = array(
        'app_id' => 'hello',
    );
    public static function config($key){
        return self::$options[$key];
    }
}

在文件中,我需要常量。

require('config.php');
print_r(app::config('app_id'));

我做的和你一样。所以一直在寻找性能优化,无论这是好的还是更好的。
NullPointer

是的,我同意这种解决方案。因为它很容易理解,所以很容易……
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

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

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

这正是我的想法。这不是一个合理的好答案吗?
Con Antonakos 2014年

这对AngularJS非常有效,因为它使用JSON。我觉得序列化答案要好得多,但是有一些理由使序列化更好吗?也许更快吗?
2014年

是的,序列化在技术上更快。但是,对于大多数需要的小集合,我更喜欢这种方法,因为它更安全。反序列化时,可能会执行代码。即使在这种情况下风险很小,我认为我们仅应在极端情况下保留用法或不进行序列化。
马里奥·阿瓦德

9

从PHP 5.6开始,您可以使用const以下关键字定义常量数组

const DEFAULT_ROLES = ['test', 'development', 'team'];

可以按以下方式访问不同的元素:

echo DEFAULT_ROLES[1]; 
....

从PHP 7开始,可以使用define以下方式定义常量数组:

define('DEFAULT_ROLES', [
    'test',
    'development',
    'team'
]);

并且可以像以前一样访问不同的元素。


3

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

<?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;

我定义它是因为我需要将对象和数组存储在常量中,因此我也将runkit安装到php中,因此可以使$ const变量成为superglobal。

您可以将其用作$const->define("my_constant",array("my","values"));$const->my_constant = array("my","values");

要获得价值,只需致电 $const->my_constant;


哇,我没料到会有这样的方式......我甚至不知道__get__set...我必须说,这种方法是伟大的。
RedClover

这些被称为魔术方法,请查阅有关它们的php文档。
Rikudou_Sennin

3

PHP 7+

从PHP 7开始,您可以只使用define()函数来定义一个常量数组:

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

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

3

甚至可以在类中使用关联数组。

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.

2

使用爆炸和内爆功能,我们可以即兴解决方案:

$array = array('lastname', 'email', 'phone');
define('DEFAULT_ROLES', implode (',' , $array));
echo explode(',' ,DEFAULT_ROLES ) [1]; 

这会回声email

如果您想对其进行更多优化,则可以定义2个函数来为您执行重复的操作,如下所示:

//function to define constant
function custom_define ($const , $array) {
    define($const, implode (',' , $array));
}

//function to access constant  
function return_by_index ($index,$const = DEFAULT_ROLES) {
            $explodedResult = explode(',' ,$const ) [$index];
    if (isset ($explodedResult))
        return explode(',' ,$const ) [$index] ;
}

希望能有所帮助。快乐的编码。


您可以通过执行以下操作来防止爆炸两次:$ explodeResult = explode(',',$ const); 如果(isset($ explodeResult)[$指数]){$返回explodeResult [$指数];}
赛义德

@Saeed是的,这很不错。我将相应地更新我的答案
MD。Sahib Bin Mahboob

2

做某种Ser / Deser或编码/解码技巧似乎很丑陋,并且要求您记住尝试使用该常数时所执行的操作。我认为带访问器的类私有静态变量是一个不错的解决方案,但我会做得更好。只需有一个公共静态getter方法即可返回常量数组的定义。这需要最少的额外代码,并且数组定义不能被意外修改。

class UserRoles {
    public static function getDefaultRoles() {
        return array('guy', 'development team');
    }
}

initMyRoles( UserRoles::getDefaultRoles() );

如果您确实想让它看起来像已定义的常量,则可以给它起一个全大写的名称,但是记住在名称后加上“()”括号会令人困惑。

class UserRoles {
    public static function DEFAULT_ROLES() { return array('guy', 'development team'); }
}

//but, then the extra () looks weird...
initMyRoles( UserRoles::DEFAULT_ROLES() );

我想您可以将方法设置为全局方法,使其更接近于您所要求的define()功能,但是无论如何,您实际上应该确定常量名称的范围,并避免使用全局方法。


2

您可以这样定义

define('GENERIC_DOMAIN',json_encode(array(
    'gmail.com','gmail.co.in','yahoo.com'
)));

$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);

2

是的,您可以将数组定义为常量。从PHP 5.6起,可以将常量定义为标量表达式,也可以定义数组常量。可以将常量定义为资源,但是应避免使用它,因为它可能导致意外的结果。

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

    // Works as of PHP 5.6.0
    const ANOTHER_CONST = CONSTANT.'; Goodbye World';
    echo ANOTHER_CONST;

    const ANIMALS = array('dog', 'cat', 'bird');
    echo ANIMALS[1]; // outputs "cat"

    // Works as of PHP 7
    define('ANIMALS', array(
        'dog',
        'cat',
        'bird'
    ));
    echo ANIMALS[1]; // outputs "cat"
?>

参考此链接

祝您编码愉快。


1

如果您从2009年开始浏览此文档,而您不喜欢AbstractSingletonFactoryGenerators,那么这里还有其他一些选择。

请记住,分配数组时会“复制”数组,或者在这种情况下返回数组,因此实际上每次都获得相同的数组。(请参阅PHP中数组的写时复制行为。)

function FRUITS_ARRAY(){
  return array('chicken', 'mushroom', 'dirt');
}

function FRUITS_ARRAY(){
  static $array = array('chicken', 'mushroom', 'dirt');
  return $array;
}

function WHAT_ANIMAL( $key ){
  static $array = (
    'Merrick' => 'Elephant',
    'Sprague' => 'Skeleton',
    'Shaun'   => 'Sheep',
  );
  return $array[ $key ];
}

function ANIMAL( $key = null ){
  static $array = (
    'Merrick' => 'Elephant',
    'Sprague' => 'Skeleton',
    'Shaun'   => 'Sheep',
  );
  return $key !== null ? $array[ $key ] : $array;
}

多年以来,我们已经能够将数组定义为常量,我认为不再采用变通方法没有太多价值。
miken32

1
@ miken32虽然为真,但提供的解决方案很有趣,没有任何其他人提供,可以根据需要在概念上应用于其他语言(将其添加到您的工具箱中)
puiu

1

如果您使用的是PHP 7和7+,则也可以使用fetch

define('TEAM', ['guy', 'development team']);
echo TEAM[0]; 
// output from system will be "guy"

0

常量只能包含标量值,建议您存储数组的序列化(或JSON编码表示形式)。


1
这不会为接受的答案添加任何内容,因此应该删除它吗?
伊恩·邓恩2012年

4
@IanDunn:我认为接受的答案并不能解释原因,或者没有为我的答案添加任何内容,但是...可以自由投票删除。
Alix Axel 2012年

1
我真的看不到所需数组的任何字符串表示形式的意义。
托马什Zato -恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.