Константы PHP, содержащие массивы?

Это не удалось:

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

Очевидно, константы не могут содержать массивы. Как лучше всего это обойти?

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

//...

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

Это кажется ненужным усилием.


person Nick Heiner    schedule 17.08.2009    source источник
comment
PHP 5.6 поддерживает постоянные массивы, см. Мой ответ ниже.   -  person Andrea    schedule 11.12.2014
comment
Когда вам нужно использовать массив в качестве константы, вы пытаетесь выполнить перечисление? Если это так, используйте SplEnum: php.net/manual/en/class.splenum.php   -  person ziGi    schedule 11.12.2014
comment
@ziGi Сегодня возникла эта проблема, нужно хранить разные типы изображений, требующие определенных размеров, стало полезно хранить эти размеры в виде постоянных массивов вместо одного для ширины и одного для высоты.   -  person Matt K    schedule 12.09.2015


Ответы (17)


ПРИМЕЧАНИЕ: хотя это принятый ответ, стоит отметить, что в PHP 5.6+ вы можете иметь константные массивы - см. Андреа Фолдс ' ответ ниже.

Вы также можете сериализовать свой массив, а затем поместить его в константу:

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

# use it
$my_fruits = unserialize (FRUITS);
person Community    schedule 17.08.2009
comment
Просто хочу сказать, что мне нравится это решение :) - person GateKiller; 25.05.2011
comment
Отлично. Но плохой момент в том, что таким образом нельзя определить константу класса. - person Gregoire; 04.08.2011
comment
лучше придерживаться статических переменных в классе. - person Jürgen Paul; 03.09.2012
comment
@Gregoire вы можете, если предварительно сериализуете значение. (фу!) - person kojiro; 06.02.2013
comment
Жаль, что ты не можешь этого сделать: $fruit = FRUITS[0]; - person Sophivorus; 22.03.2013
comment
Фелипе, вы можете сделать _1 _... FRUITS - это строка (не массив - это результат сериализации массива), поэтому вам необходимо десериализовать его, чтобы вернуть массив. - person Armfoot; 27.06.2013
comment
Это было именно то, что мне нужно для передачи нескольких значений в объект, определяемый пользователем! I.E .: типы сотрудников как массив. - person David J Eddy; 16.07.2013
comment
Этот код элегантный, но довольно медленный. Гораздо лучше использовать метод общедоступного статического класса, который возвращает массив. - person noun; 03.09.2013
comment
просто отметьте здесь, что в PHP 5.6 теперь можно иметь константные массивы .. const fruits = ['apple', 'cherry', 'banana']; - person Alex K; 28.11.2014
comment
Это решение должно быть УСТАРЕВШИМ из-за недостаточной производительности! - person Loenix; 18.10.2015
comment
Это хорошая альтернатива значениям, разделенным вертикальной чертой. Я думаю, что утверждение, что вызов _1 _ / _ 2_ является медленным, преувеличивает его вклад в общее время выполнения сценария. - person jeteon; 16.11.2015
comment
@Loenix, Говорят, что вы можете создавать постоянные массивы, начиная с php 5.6, но если у кого-то (например, у меня) есть более ранний php, это совершенно правильно. - person ; 10.03.2017
comment
@Soaku В этом случае вы должны использовать решение Рави Хирани или явную функцию, возвращающую массив, это должно быть устаревшим во всех случаях. - person Loenix; 11.03.2017
comment
@ Лоеникс, почему? Это реальный способ хранения массива в константе, в то время как решение RaviHirani не использует реальную константу. И он используется даже дольше, чем этот. И как бы вы осудили то, что является просто сниппетом? - person ; 11.03.2017
comment
@Soaku, потому что это не массив, а строка, и вам придется десериализовать ее каждый раз, когда вы ее используете. Так что предпочтите функцию, возвращающую массив, который лучше для производительности, и это реальное решение, подобное константе. - person Loenix; 12.03.2017
comment
@Loenix, возможно, но его решение также требует дополнительного набора текста каждый раз, когда вы его используете, даже если это не нужно. Решение Rikudou_Sennin выглядит лучше, - person ; 12.03.2017

Начиная с 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'));
person Andrea    schedule 11.12.2014
comment
За это нужно проголосовать, так как все остальные ответы устарели или просто написаны дезинформированными пользователями. - person Andreas Bergström; 19.12.2014
comment
Это единственный синтаксис? Можете ли вы использовать старую функцию определения? определить ('ARRAY_CONSTANT', массив ('элемент1', 'элемент2', 'элемент3')); - person Jack; 20.12.2014
comment
@JackNicholsonn К сожалению, вы не можете использовать define() здесь, в PHP 5.6, но исправлено для PHP 7.0. :) - person Andrea; 21.12.2014
comment
@ AndreasBergström Нет, это слишком новый вопрос. Этот вопрос был задан в 2009 году! Этот синтаксис будет почти бесполезен для большинства пользователей в наши дни. Почти у всех есть PHP 5.6 на своих серверах. Другие ответы прекрасны, поскольку они также предлагают альтернативы. Принятый ответ - это пока единственный жизнеспособный способ, если вы не хотите использовать классы. - person Ismael Miguel; 14.01.2015
comment
@IsmaelMiguel, не надо быть уверенным, что у всех них 5.6. Кто-нибудь на сервере Windows только что получил драйверы сервера 5.6 sql от Microsoft около месяца назад. - person M H; 09.07.2015
comment
почти готово! Еще 8 голосов !! :п. Однако, если бы этот ответ включал ответ PHP ‹5.6, было бы еще лучше - person Damon; 14.06.2016
comment
Aaaarrrgh ... В PHP 5.6 вы можете определить значение константы как функция, возвращающая значение, если вы используете ключевое слово define. Вы можете использовать массивы, когда определяете его с помощью const, но ни одна функция не возвращает значение. И нет возможности как-то перемешать. Только в php7. вздох... - person vaso123; 18.01.2017
comment
@ vaso123 один обходной путь - сделать что-то вроде: eval("const $constname = " . var_export($somevariable) . ";"); - не уверен, что я бы рекомендовал это, хотя - person Andrea; 18.01.2017
comment
@Andrea Lol ... Никогда, ни за что. eval это зло. To define(serialize([...])); выполняет эту работу за меня, к счастью, у меня всего 2 массива, и эти массивы не слишком большие. Я мог бы написать вспомогательный класс для получения этих значений, я просто хочу использовать преимущества своей IDE. В следующий раз ... когда мы начнем использовать PHP 7. - person vaso123; 19.01.2017
comment
Очевидно, что короткий синтаксис работает и для PHP7, не знаю, почему бы вам не использовать его ([] вместо array ()). - person klidifia; 15.03.2020
comment
Потому что это то, что делал исходный вопрос. - person Andrea; 15.03.2020

Вы можете хранить их как статические переменные класса:

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'];
person soulmerge    schedule 17.08.2009
comment
+1. Я к этому иду годами: const AtomicValue =42; public static $fooArray = ('how','di') - person Frank Nocke; 07.05.2012
comment
Хотя мне кажется смешным, что мы не можем создавать неизменяемые массивы в php, это обеспечивает достойный обходной путь. - person Akoi Meexx; 28.08.2012
comment
Если вы часто используете константу, я бы определенно избегал вызова функции, они довольно дороги. Статика - это лучший способ. - person Chris Seufert; 31.10.2014
comment
Это решение оказалось гораздо более крутым, чем я ожидал: мне нужна была только часть значений массива, поэтому вместо того, чтобы просто получить массив, я использовал некоторые параметры в функции. В моем случае Constants :: getRelatedIDs ($ myID) дает мне внутренний массив только с нужными мне значениями (я также провожу некоторую проверку идентификатора внутри этой функции). @cseufert получение всего массива и фильтрация для каждого случая было бы для меня намного дороже ... - person Armfoot; 07.05.2015
comment
наличие функции (getArray) с частным статическим членом - лучшее представление для констант, поскольку они могут быть изменениями ???????? - person Kamaldeep singh Bhatia; 23.01.2017

Если вы используете PHP 5.6 или выше, используйте ответ Андреа Фолдс

Я так и использую. Надеюсь, это поможет другим.

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'));
person Jashwant    schedule 26.07.2012
comment
Я сделал то же самое, что и ты. Так что искал оптимизацию производительности, хорошо это или что-то еще, если лучше. - person NullPointer; 17.01.2017
comment
Я согласен с этим решением. Поскольку это просто и понятно ... - person Faris Rayhan; 16.10.2017

Это то, что я использую. Это похоже на пример, предоставленный 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'
person Syclone    schedule 04.05.2013

Вы можете сохранить его как строку JSON в константе. С точки зрения приложения, JSON может быть полезен и в других случаях.

define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));    
$fruits = json_decode (FRUITS);    
var_dump($fruits);
person Mahesh Talpade    schedule 29.07.2013
comment
Это именно то, о чем я думал. Разве это не законно хороший ответ? - person Con Antonakos; 01.07.2014
comment
Это действительно хорошо работает с AngularJS, потому что он потребляет JSON. Я чувствую, что это намного лучше, чем ответ сериализации, но есть ли причина, по которой сериализация лучше? Возможно, это быстрее? - person Drellgor; 19.09.2014
comment
Да, сериализация технически быстрее. Однако для небольших наборов, которые необходимы в основном, я предпочитаю этот метод, поскольку он более безопасен. При десериализации код может быть выполнен. Даже если в данном случае это очень низкий риск, я думаю, нам следует зарезервировать использование или десериализацию только для крайних случаев. - person Mario Awad; 08.12.2014

Начиная с PHP 5.6, вы можете определять постоянные массивы с помощью ключевого слова const, как показано ниже.

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

Доступ к различным элементам можно получить, как показано ниже:

echo DEFAULT_ROLES[1]; 
....

Начиная с PHP 7, постоянные массивы можно определять с помощью define, как показано ниже:

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

и к различным элементам можно получить доступ так же, как и раньше.

person Altaf Hussain    schedule 26.01.2016

PHP 7+

Начиная с PHP 7, вы можете просто использовать define () для определения постоянного массива:

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

echo ANIMALS[1]; // outputs "cat"
person Rabin Lama Dong    schedule 06.07.2017

Я знаю, что это немного старый вопрос, но вот мое решение:

<?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 суперглобальной.

Вы можете использовать его как $const->define("my_constant",array("my","values")); или просто $const->my_constant = array("my","values");

Чтобы получить значение, просто позвоните $const->my_constant;

person Rikudou_Sennin    schedule 25.10.2014
comment
Ух, не ожидал такого ... Я даже не знал про __get и _2 _... Сразу скажу, что это отличный метод. - person ; 10.03.2017
comment
Это так называемые магические методы, проверьте их в документации php. - person Rikudou_Sennin; 20.03.2017

Да, вы можете определить массив как постоянный. Начиная с 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"
?>

Со ссылкой на эту ссылку

Удачного кодирования.

person Sahil Patel    schedule 14.04.2017

Может даже работать с ассоциативными массивами ... например, в классе.

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.
person Thielicious    schedule 21.10.2017

Используя функции разнесения и взрыва, мы можем импровизировать решение:

$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] ;
}

Надеюсь, это поможет . Удачного кодирования.

person MD. Sahib Bin Mahboob    schedule 13.11.2012
comment
вы можете предотвратить двойной взрыв, выполнив: $ explodeResult = explode (',', $ const); if (isset ($ explodeResult) [$ index]) {return $ explodeResult [$ index];} - person Saeed; 02.07.2013
comment
@Saeed Ага, это хороший момент. Я обновлю свой ответ соответственно - person MD. Sahib Bin Mahboob; 07.07.2013

Выполнение какого-либо трюка с последовательным / кодированием или кодированием / декодированием кажется уродливым и требует от вас вспомнить, что именно вы делали, когда пытаетесь использовать константу. Я думаю, что приватная статическая переменная класса с аксессором - достойное решение, но я сделаю вам одно лучше. Просто имейте общедоступный статический метод получения, который возвращает определение постоянного массива. Для этого требуется минимум дополнительного кода, и определение массива не может быть случайно изменено.

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 (), которую вы просили, но вы действительно должны в любом случае ограничить имя константы и избегать глобальных переменных.

person Daniel Skarbek    schedule 06.02.2014

Вы можете определить так

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

$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);
person Fawwad    schedule 09.03.2016

Если вы смотрите на это с 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;
}
person biziclop    schedule 28.11.2018
comment
Мы можем определять массивы как константы уже много лет, и я не думаю, что больше пользы от тупых обходных путей. - person miken32; 29.11.2018
comment
@ miken32 хотя и верно, предоставленное решение интересно, не было предоставлено кем-либо другим и может быть концептуально применено к другим языкам по мере необходимости (добавьте его в свой ящик для инструментов) - person puiu; 26.02.2019

если вы используете PHP 7 и 7+, вы также можете использовать такую ​​же выборку

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

Константы могут содержать только скалярные значения, я предлагаю вам сохранить сериализацию (или представление в кодировке JSON) массива.

person Alix Axel    schedule 17.08.2009
comment
Это ничего не добавляет к принятому ответу, так что, может быть, его следует удалить? - person Ian Dunn; 15.09.2012
comment
@IanDunn: Я бы сказал, что принятый ответ не объясняет почему, или что он ничего не добавляет к моему ответу, но ... Не стесняйтесь голосовать за удаление. - person Alix Axel; 16.09.2012
comment
Я действительно не вижу смысла в строковом представлении желаемого массива. - person Tomáš Zato - Reinstate Monica; 15.01.2013