Константи PHP, що містять масиви?


407

Не вдалося:

 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 У цьому питанні сьогодні виникли різні типи зображень для зберігання, які потребують конкретних розмірів, стало корисно зберігати ці параметри як постійні масиви замість одного для ширини та одного для висоти.
— Метт К

Відповіді:


498

ПРИМІТКА. Хоча це прийнята відповідь, варто зазначити, що в PHP 5.6+ ви можете мати масиви const - див. Відповідь Андреа Фолдса нижче .

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

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

# use it
$my_fruits = unserialize (FRUITS);

40
Просто хочу сказати, що я люблю це рішення :)
— GateKiller

16
Приємно. Але погано в тому, що ви не можете визначати константу постійної таким чином.
— Gregoire

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
Це потрібно прихилити, оскільки всі інші відповіді застаріли або просто написані дезінформованими користувачами.
— Andreas Bergström

Це єдиний синтаксис? Чи можете ви використовувати стару функцію визначення? 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 Server щойно отримав драйвери сервера 5.6 sql від microsoft близько місяця тому.
— MH

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

Якщо вам не подобається думка про те, що масив можуть бути змінені іншими, getter може допомогти:

class Constants {
    private static $array = array('guy', 'development team');
    public static function getArray() {
        return self::$array;
    }
}
$constantArray = Constants::getArray();

EDIT

Починаючи з PHP5.4, можна навіть отримати доступ до значень масиву без необхідності проміжних змінних, тобто таких робіт:

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

1
+1. Я збираюся цього зробити роками:const AtomicValue =42; public static $fooArray = ('how','di')
— Френк Нокк

9
Хоча мені здається смішним, що ми не можемо створити незмінні масиви в php, це забезпечує гідний спосіб вирішення.
— Akoi Meexx

Якщо ви використовуєте константу багато, я б точно уникав виклику функції, вони досить дорогі. Статичний - це шлях.
— Кріс Сеуферт

1
Це рішення було набагато приголомшливішим, ніж я очікував: мені потрібна була лише частина значень масиву, тому замість того, щоб просто отримати масив, я використав деякі параметри функції. У моєму випадку Constants :: getRelatedIDs ($ myID) отримує мені внутрішній масив із лише потрібними мені значеннями (я також роблю деяку перевірку ідентифікатора всередині цієї функції). @cseufert отримання всього масиву та фільтрація для кожного випадку буде для мене набагато дорожче ...
— Armfoot

1
функція (getArray) з приватним статичним членом - найкраще представлення для констант, оскільки вони можуть бути змінені 👍🏻
— Kamaldeep singh Bhatia

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

Я погоджуюся з цим рішенням. Як це просто і легко зрозуміти ...
— Фаріс Райхан

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

Це дуже добре працює з 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;


Нічого собі, я не очікував такого шляху ... Я навіть про це не знав __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

За допомогою функції explode and implode ми можемо імпровізувати рішення:

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

Це відлунне email.

Якщо ви хочете, щоб його оптимізували більше, ви можете визначити дві функції, щоб зробити такі повторювані речі, як вам:

//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

@Saeed ю, це приємний момент. Я відповідно оновлю свою відповідь
— доктор медичних наук. Сахіб Бін Махбоб

2

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

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+, ви можете також використовувати такий доступ

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

0

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


1
Це не додає нічого до прийнятої відповіді, тому, можливо, її слід видалити?
— Ян Данн

4
@IanDunn: Я б заперечував, що прийнята відповідь не пояснює, чому, або що вона нічого не додає до моєї відповіді, але ... Не соромтеся голосувати за видалення.
— Алікс Аксель

1
Я насправді не бачу сенсу жодного рядкового подання потрібного масиву.
— Томаш Зато - Відновіть Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.