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

408

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

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

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

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

//...

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

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

Ник Хейнер
источник
17
PHP 5.6 поддерживает постоянные массивы, см. Мой ответ ниже.
Андреа
1
Когда вам нужно использовать массив в качестве константы, вы пытаетесь сделать перечисление? Если так, то используйте SplEnum: php.net/manual/en/class.splenum.php
ziGi
2
@ziGi Сегодня мы столкнулись с этой проблемой, для хранения различных типов изображений, требующих определенных размеров, стало полезно хранить эти измерения в виде постоянных массивов вместо одного для ширины и одного для высоты.
Мэтт К

Ответы:

499

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

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

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

# use it
$my_fruits = unserialize (FRUITS);
Сообщество
источник
40
Просто хочу сказать, что я люблю это решение :)
GateKiller
17
Ницца. Но плохой момент в том, что вы не можете определить константу класса таким образом.
Грегуар
19
лучше придерживаться статических переменных в классе.
Юрген Пол
5
Жаль, что вы не можете сделать:$fruit = FRUITS[0];
Sophivorus
20
Этот код элегантный, но довольно медленный. Намного лучше использовать публичный статический метод класса, который возвращает массив.
существительное
845

Начиная с 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'));
Andrea
источник
41
Это должно быть поддержано, поскольку все другие ответы устарели или просто написаны дезинформированными пользователями.
Андреас Бергстрем
Это единственный синтаксис? Вы можете использовать старую функцию определения? define ('ARRAY_CONSTANT', массив ('item1', 'item2', 'item3'));
Джек,
5
@JackNicholsonn К сожалению, вы не можете использовать define()здесь в PHP 5.6, но это было исправлено в PHP 7.0 . :)
Андреа
@ AndreasBergström Нет, этот вопрос слишком новый. Этот вопрос был сделан в 2009 году! Этот синтаксис будет почти бесполезен для большинства пользователей в наши дни. Почти каждый имеет PHP 5.6 на своих серверах. Другие ответы прекрасно, так как они также предлагают альтернативы. Принятый ответ пока является единственным жизнеспособным способом, если вы не хотите использовать классы.
Исмаэль Мигель
@IsmaelMiguel не уверен, что у них всех 5,6. Любой на сервере Windows только что получил драйверы сервера 5.6 sql от Microsoft около месяца назад.
МЗ
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'];
soulmerge
источник
1
+1. Я собираюсь на это годами:const AtomicValue =42; public static $fooArray = ('how','di')
Фрэнк Нок
9
Хотя мне кажется смешным, что мы не можем создавать неизменяемые массивы в php, это обеспечивает достойный обходной путь.
Akoi Meexx
Если вы часто используете константу, я бы определенно избегал вызова функций, они довольно дорогие. Статика это путь.
Крис Сеуферт
1
Это решение оказалось намного более удивительным, чем я ожидал: мне нужна была только часть значений массива, поэтому вместо простого получения массива я использовал некоторые параметры в функции. В моем случае Constants :: getRelatedIDs ($ myID) возвращает мне внутренний массив с нужными мне значениями (я также провожу некоторую проверку идентификатора внутри этой функции). @cseufert получение всего массива и фильтрация для каждого случая будет для меня намного дороже ...
Armfoot
1
наличие функции (getArray) с закрытым статическим членом является лучшим представлением для констант, поскольку они могут быть изменениями 👍🏻
Камалдип Сингх Бхатия
41

Если вы используете 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'));
Jashwant
источник
Я сделал то же самое, что и ты. Так что искал оптимизацию производительности, хорошо это или что-то еще, если лучше.
NullPointer
Я согласен с этим решением. Как это просто и легко понять ...
Фарис Райхан
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'
Syclone
источник
10

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

define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));    
$fruits = json_decode (FRUITS);    
var_dump($fruits);
Махеш Талпаде
источник
Это именно то, о чем я думал. Разве это не законно хороший ответ?
Кон Антонакос
Это действительно хорошо работает с AngularJS, потому что он использует JSON. Я чувствую, что это намного лучше, чем ответ сериализации, но есть ли причина, почему сериализация лучше? Может быть, это быстрее?
Дреллгор
Да, сериализация технически быстрее. Тем не менее, для небольших наборов, которые в основном нужны, я предпочитаю этот метод, так как он безопаснее. Когда вы отменяете сериализацию, код может быть выполнен. Даже если в этом случае это очень низкий риск, я думаю, что мы должны зарезервировать использование или не сериализовать только для крайних случаев.
Марио Авад
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 суперглобальной.

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

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

Rikudou Sennin
источник
Ух ты, я не ожидал такого пути ... Я даже не знал о ... __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.
Thielicious
источник
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] ;
}

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

MD. Сахиб бин Махбуб
источник
вы можете предотвратить взрыв два раза, выполнив: $ explodeResult = explode (',', $ const); if (isset ($ explodeResult) [$ index]) {return $ explodeResult [$ index];}
Саид
@ Seed да, это хороший момент. Я буду обновлять свой ответ соответственно
MD. Сахиб бин Махбуб
2

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

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);
Fawwad
источник
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;
}
biziclop
источник
Уже много лет мы можем определять массивы как константы, и я не думаю, что есть какая-то ценность для тупых обходных путей.
miken32
1
@ miken32 Хотя это и правда, предоставленное решение интересно, не было поставлено кем-либо еще и может быть концептуально применено к другим языкам по мере необходимости (добавьте его в свой
набор
1

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

define('TEAM', ['guy', 'development team']);
echo TEAM[0]; 
// output from system will be "guy"
Mac Rathod
источник
0

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

Аликс Аксель
источник
1
Это ничего не добавляет к принятому ответу, поэтому, возможно, его следует удалить?
Ян Данн
4
@IanDunn: Я бы сказал, что принятый ответ не объясняет почему или что он ничего не добавляет к моему ответу, но ... Вы можете голосовать за удаление.
Аликс Аксель
1
Я не вижу смысла в любом строковом представлении нужного массива.
Томаш Зато - Восстановить Монику