Константи 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.