【问题标题】:PHP Constants Containing Arrays?包含数组的 PHP 常量?
【发布时间】:2010-11-20 09:23:50
【问题描述】:

这失败了:

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

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

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

//...

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

这似乎是不必要的努力。

【问题讨论】:

  • PHP 5.6 支持常量数组,请看下面我的回答。
  • 什么时候需要使用数组作为常量,您是否要进行枚举?如果是,则使用 SplEnum:php.net/manual/en/class.splenum.php
  • @ziGi 今天遇到了这个问题,需要存储不同类型的图像需要特定的尺寸,将这些尺寸存储为常量数组而不是一个用于宽度和一个用于高度的数组变得很有用。跨度>

标签: php arrays constants scalar


【解决方案1】:

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

【讨论】:

  • 这需要被投票,因为所有其他答案都已过时或只是由误传的用户写的。
  • 这是唯一的语法吗?您可以使用旧的定义功能吗?定义('ARRAY_CONSTANT', 数组('item1', 'item2', 'item3'));
  • @JackNicholsonn 不幸的是,您不能在 PHP 5.6 中使用define(),但this has been fixed for PHP 7.0。 :)
  • @AndreasBergström 不,这个问题太新了。这个问题是2009年提出的!对于现在的大多数用户来说,这种语法几乎毫无用处。几乎每个人的服务器上都有 PHP 5.6。其他答案非常好,因为它们也提供了替代方案。如果您不想使用类,则接受的答案是迄今为止唯一可行的方法。
  • @IsmaelMiguel 不要那么确定他们都有 5.6。大约一个月前,windows server 上的任何人都从 microsoft 获得了 5.6 sql server 驱动程序。
【解决方案2】:

注意:虽然这是公认的答案,但值得注意的是,在 PHP 5.6+ 中,您可以使用 const 数组 - see Andrea Faulds' answer below

你也可以序列化你的数组,然后放入常量中:

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

# use it
$my_fruits = unserialize (FRUITS);

【讨论】:

  • 只想说我喜欢这个解决方案:)
  • 不错。但不好的一点是你不能用这种方式定义一个类常量。
  • 在类中更好地坚持静态变量。
  • 可惜你做不到:$fruit = FRUITS[0];
  • 这段代码很优雅但是很慢。使用返回数组的公共静态类方法要好得多。
【解决方案3】:

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

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。我会为此奋斗多年:const AtomicValue =42; public static $fooArray = ('how','di')
  • 虽然我们不能在 php 中创建不可变数组对我来说似乎很荒谬,但这提供了一个不错的解决方法。
  • 如果你经常使用常量,我肯定会避免调用函数,它们非常昂贵。静态是要走的路。
  • 这个解决方案比我预期的要棒得多:我只需要数组的一部分值,因此我不是简单地获取数组,而是在函数中使用了一些参数。在我的例子中, Constants::getRelatedIDs($myID) 为我提供了一个内部数组,其中包含我需要的值(我还在这个函数中进行了一些 ID 验证)。 @cseufert 获取整个数组并针对每种情况进行过滤对我来说要贵得多...
  • 拥有一个带有私有静态成员的函数(getArray)是常量的最佳表示,因为它们可以改变??
【解决方案4】:

If you are using PHP 5.6 or above, use Andrea Faulds answer

我就是这样使用它的。我希望,它会帮助其他人。

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

【讨论】:

  • 我和你一样。所以一直在寻找性能优化,无论这是好还是其他更好。
  • 是的,我同意这个解决方案。因为它简单易懂...
【解决方案5】:

这是我使用的。它类似于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'

【讨论】:

    【解决方案6】:

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

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

    【讨论】:

    • 这正是我的想法。这不是一个合法的好答案吗?
    • 这对 AngularJS 非常有效,因为它使用 JSON。我觉得这比序列化答案要好得多,但是序列化更好有什么原因吗?是不是更快?
    • 是的,序列化在技术上更快。但是,对于最需要的小型设备,我更喜欢这种方法,因为它更安全。反序列化时,可能会执行代码。即使在这种情况下这是一个非常低的风险,我认为我们应该只为极端情况保留使用或反序列化。
    【解决方案7】:

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

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

    不同的元素可以访问如下:

    echo DEFAULT_ROLES[1]; 
    ....
    

    从 PHP 7 开始,可以使用define 定义常量数组,如下所示:

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

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

    【讨论】:

      【解决方案8】:

      PHP 7+

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

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

      【讨论】:

        【解决方案9】:

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

        <?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-&gt;define("my_constant",array("my","values")); 或只是$const-&gt;my_constant = array("my","values");

        要获取值,只需调用$const-&gt;my_constant;

        【讨论】:

        • 哇,我没想到会这样……我什至不知道__get__set……我必须说这个方法很棒。
        • 这些被称为魔法方法,查看 php 文档了解它们。
        【解决方案10】:

        是的,您可以将数组定义为常量。从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"
        ?>
        

        参考this link

        祝你编码愉快。

        【讨论】:

          【解决方案11】:

          甚至可以使用关联数组.. 例如在一个类中。

          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.
          

          【讨论】:

            【解决方案12】:

            使用 explode 和 implode 函数我们可以即兴解决:

            $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 ); if(isset($explodeResult)[$index]){return $explodeResult[$index];}
            • @Saeed 是的,这是一个很好的观点。我会相应地更新我的答案
            【解决方案13】:

            执行某种 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() 功能,但无论如何您确实应该限定常量名称并避免使用全局变量。

            【讨论】:

              【解决方案14】:

              你可以这样定义

              define('GENERIC_DOMAIN',json_encode(array(
                  'gmail.com','gmail.co.in','yahoo.com'
              )));
              
              $domains = json_decode(GENERIC_DOMAIN);
              var_dump($domains);
              

              【讨论】:

                【解决方案15】:

                如果你使用的是 PHP 7 & 7+,你也可以像这样使用 fetch

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

                【讨论】:

                  【解决方案16】:

                  如果您是从 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 虽然是真的,但提供的解决方案很有趣,不是由其他任何人提供的,并且可以根据需要在概念上应用于其他语言(将其添加到您的工具箱中)
                  【解决方案17】:

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

                  【讨论】:

                  • 这不会为接受的答案添加任何内容,所以也许应该删除它?
                  • @IanDunn:我认为接受的答案没有解释原因,或者它没有为我的答案添加任何内容,但是......尽管请随意投票删除。
                  • 我没有真正看到所需数组的任何字符串表示形式的意义。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-05-17
                  • 2016-11-27
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多