Stałe PHP zawierające tablice?


407

To się nie udało:

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

Najwyraźniej stałe nie mogą przechowywać tablic. Jaki jest najlepszy sposób na obejście tego?

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

//...

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

To wydaje się niepotrzebnym wysiłkiem.


17
PHP 5.6 obsługuje stałe tablice, zobacz moją odpowiedź poniżej.
Andrea,

1
Kiedy trzeba użyć tablicy jako stałej, czy próbujesz wykonać wyliczenie? Jeśli tak, użyj SplEnum: php.net/manual/en/class.splenum.php
ziGi

2
@ziGi Przyszedł dziś ten problem, mają różne rodzaje obrazów do przechowywania, które wymagają określonych wymiarów, przydało się przechowywanie tych wymiarów jako stałych tablic zamiast jednego dla szerokości i jednego dla wysokości.
Matt K

Odpowiedzi:


498

UWAGA: chociaż jest to zaakceptowana odpowiedź, warto zauważyć, że w PHP 5.6+ możesz mieć stałe tablice - patrz odpowiedź Andrei Faulds poniżej .

Możesz również serializować tablicę, a następnie umieścić ją w stałej:

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

# use it
$my_fruits = unserialize (FRUITS);

40
Chcę tylko powiedzieć, że uwielbiam to rozwiązanie :)
GateKiller

16
Miły. Ale wadą jest to, że nie można w ten sposób zdefiniować stałej klasy.
Gregoire,

19
lepiej trzymać się zmiennych statycznych w klasie.
Jürgen Paul,

5
Szkoda, że ​​nie możesz:$fruit = FRUITS[0];
Sophivorus

20
Ten kod jest elegancki, ale dość powolny. O wiele lepiej jest użyć publicznej metody klasy statycznej, która zwraca tablicę.
rzeczownik

844

Od wersji PHP 5.6 możesz zadeklarować stałą tablicy za pomocą const:

<?php
const DEFAULT_ROLES = array('guy', 'development team');

Krótka składnia również działa, jak można się spodziewać:

<?php
const DEFAULT_ROLES = ['guy', 'development team'];

Jeśli masz PHP 7, możesz w końcu użyć define(), tak jak wcześniej próbowałeś:

<?php
define('DEFAULT_ROLES', array('guy', 'development team'));

41
Należy to ocenić, ponieważ wszystkie inne odpowiedzi są nieaktualne lub zostały napisane przez źle poinformowanych użytkowników.
Andreas Bergström,

Czy to jedyna składnia? Czy możesz użyć starej funkcji definiowania? Zdefiniuj („ARRAY_CONSTANT”, tablica („item1”, „item2”, „item3”));
Jack

5
@JackNicholsonn Niestety nie możesz używać tego define()tutaj w PHP 5.6, ale zostało to naprawione w PHP 7.0 . :)
Andrea

@ AndreasBergström Nie, to pytanie jest zbyt nowe. To pytanie powstało w 2009 roku! Ta składnia będzie prawie bezużyteczna dla większości użytkowników obecnie. Prawie każdy ma PHP 5.6 na swoich serwerach. Pozostałe odpowiedzi są w porządku, ponieważ oferują również alternatywy. Zaakceptowana odpowiedź jest jak dotąd jedynym realnym sposobem, jeśli nie chcesz korzystać z klas.
Ismael Miguel

@ IsmaelMiguel nie bądź pewien, że wszyscy mają 5.6. Każdy na serwerze Windows właśnie dostał sterowniki serwera 5.6 sql od microsoft około miesiąc temu.
MH

141

Możesz przechowywać je jako zmienne statyczne klasy:

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

Jeśli nie podoba Ci się pomysł, że tablica może być zmieniana przez innych, getter może pomóc:

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

EDYTOWAĆ

Od PHP5.4 można nawet uzyskać dostęp do wartości tablic bez potrzeby stosowania zmiennych pośrednich, tj. Następujące działania:

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

1
+1. Idę na to od lat:const AtomicValue =42; public static $fooArray = ('how','di')
Frank Nocke

9
Chociaż wydaje mi się śmieszne, że nie możemy stworzyć niezmiennych tablic w php, zapewnia to przyzwoite obejście.
Akoi Meexx

Jeśli często używasz stałej, zdecydowanie unikałbym wywołania funkcji, są one dość drogie. Statyczna jest droga.
Chris Seufert

1
To rozwiązanie było o wiele bardziej niesamowite niż się spodziewałem: potrzebowałem tylko części wartości tablicy, dlatego zamiast po prostu uzyskać tablicę, użyłem pewnych parametrów w funkcji. W moim przypadku Constants :: getRelatedIDs ($ myID) zapewnia mi wewnętrzną tablicę zawierającą tylko te wartości, których potrzebowałem (wykonuję również weryfikację ID w ramach tej funkcji). @ cseufert uzyskanie całej tablicy i filtrowanie dla każdej sprawy byłoby dla mnie znacznie droższe ...
Armfoot

1
posiadanie funkcji (getArray) z prywatnym elementem statycznym jest najlepszą reprezentacją dla stałych, ponieważ mogą one być zmianami 👍🏻
Kamaldeep singh Bhatia

41

Jeśli używasz PHP 5.6 lub nowszego, użyj odpowiedzi Andrei Faulds

Używam tego w ten sposób. Mam nadzieję, że pomoże innym.

config.php

class app{
    private static $options = array(
        'app_id' => 'hello',
    );
    public static function config($key){
        return self::$options[$key];
    }
}

W pliku, w którym potrzebuję stałych.

require('config.php');
print_r(app::config('app_id'));

Zrobiłem to samo co ty. Tak więc szukałem optymalizacji wydajności, czy to jest dobre, czy coś innego, jeśli jest lepsze.
NullPointer

Tak, zgadzam się z tym rozwiązaniem. Jak to jest proste i łatwe do zrozumienia ...
Faris Rayhan

12

Tego używam. Jest podobny do przykładu dostarczonego przez soulmerge, ale w ten sposób można uzyskać pełną tablicę lub tylko jedną wartość w tablicy.

class Constants {
    private static $array = array(0 => 'apple', 1 => 'orange');

    public static function getArray($index = false) {
        return $index !== false ? self::$array[$index] : self::$array;
    }
}

Użyj tego w ten sposób:

Constants::getArray(); // Full array
// OR 
Constants::getArray(1); // Value of 1 which is 'orange'

10

Możesz przechowywać go jako ciąg JSON w stałej. Z punktu widzenia aplikacji JSON może być przydatny w innych przypadkach.

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

Właśnie o tym myślałem. Czy to nie jest uzasadniona odpowiedź?
Con Antonakos

Działa to naprawdę dobrze z AngularJS, ponieważ zużywa JSON. Wydaje mi się, że jest to znacznie lepsze niż odpowiedź serializująca, ale czy istnieje jakiś powód, dla którego serializacja jest lepsza? Czy to może szybsze?
Drellgor,

Tak serializacja jest technicznie szybsza. Jednak w przypadku małych zestawów, które są najbardziej potrzebne, wolę tę metodę, ponieważ jest bezpieczniejsza. Po odserializowaniu kod może zostać wykonany. Nawet jeśli w tym przypadku jest to bardzo niskie ryzyko, myślę, że powinniśmy zarezerwować użycie lub odserializować tylko w skrajnych przypadkach.
Mario Awad,

9

Począwszy od PHP 5.6, możesz definiować stałe tablice używając constsłowa kluczowego jak poniżej

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

i różne elementy są dostępne jak poniżej:

echo DEFAULT_ROLES[1]; 
....

Począwszy od PHP 7, stałe tablice można zdefiniować, korzystając z defineponiższego opisu:

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

i do różnych elementów można uzyskać dostęp w taki sam sposób jak poprzednio.


3

Wiem, że to trochę stare pytanie, ale oto moje rozwiązanie:

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

Zdefiniowałem to, ponieważ musiałem przechowywać obiekty i tablice w stałych, więc zainstalowałem także runkit na php, aby móc zmienić zmienną $ const na superglobalną.

Możesz użyć go jako $const->define("my_constant",array("my","values"));lub po prostu$const->my_constant = array("my","values");

Aby uzyskać wartość, wystarczy zadzwonić $const->my_constant;


Wow, nie spodziewałem się takiego sposobu ... Nawet o tym nie wiedziałem __geti __set... Muszę powiedzieć, że ta metoda jest świetna.
RedClover,

Są to tak zwane magiczne metody, sprawdź dokumentację php na ich temat.
Rikudou_Sennin

3

PHP 7+

Począwszy od PHP 7, możesz po prostu użyć funkcji defin (), aby zdefiniować stałą tablicę:

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

echo ANIMALS[1]; // outputs "cat"

3

Może nawet pracować z tablicami asocjacyjnymi ... na przykład w klasie.

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

Korzystając z funkcji wybuchania i implodowania, możemy improwizować rozwiązanie:

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

To odbije się echem email.

Jeśli chcesz go bardziej zoptymalizować, możesz zdefiniować 2 funkcje, które będą wykonywać powtarzające się czynności:

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

Mam nadzieję, że to pomaga. Szczęśliwego kodowania.


możesz zapobiec wybuchowi dwa razy, wykonując: $ explodeResult = explode (',', $ const); if (isset ($ explodeResult) [$ index]) {return $ explodeResult [$ index];}
Saeed

@ Tak, to fajna sprawa. Odpowiednio zaktualizuję swoją odpowiedź
MD. Sahib Bin Mahboob,

2

Wykonanie jakiejś sztuczki ser / deser lub kodowania / dekodowania wydaje się brzydkie i wymaga zapamiętania, co dokładnie zrobiłeś, gdy próbujesz użyć stałej. Myślę, że prywatna zmienna statyczna klasy z akcesorium jest przyzwoitym rozwiązaniem, ale zrobię ci to lepiej. Po prostu skorzystaj z publicznej metody pobierania statycznego, która zwraca definicję stałej tablicy. Wymaga to minimum kodu i definicji tablicy nie można przypadkowo zmodyfikować.

class UserRoles {
    public static function getDefaultRoles() {
        return array('guy', 'development team');
    }
}

initMyRoles( UserRoles::getDefaultRoles() );

Jeśli naprawdę chcesz, aby wyglądał jak zdefiniowana stała, możesz nadać mu nazwę wielkimi literami, ale byłoby mylące, aby pamiętać o dodawaniu nawiasów „()” po nazwie.

class UserRoles {
    public static function DEFAULT_ROLES() { return array('guy', 'development team'); }
}

//but, then the extra () looks weird...
initMyRoles( UserRoles::DEFAULT_ROLES() );

Podejrzewam, że możesz sprawić, by metoda globalna była bliższa funkcjom definiowania (), o które prosiłeś, ale naprawdę powinieneś tak czy inaczej zawrzeć stałą nazwę i unikać globalizacji.


2

Możesz zdefiniować w ten sposób

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

$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);

2

Tak, możesz zdefiniować tablicę jako stałą. Począwszy od PHP 5.6 , można zdefiniować stałą jako wyrażenie skalarne, a także można zdefiniować stałą tablicową . Można zdefiniować stałe jako zasób, ale należy tego unikać, ponieważ może to spowodować nieoczekiwane wyniki.

<?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"
?>

Z odniesieniem do tego linku

Miłego kodowania.


1

Jeśli szukasz tego od 2009 roku i nie lubisz AbstractSingletonFactoryGenerators, oto kilka innych opcji.

Pamiętaj, że tablice są „kopiowane” po przypisaniu lub w tym przypadku zwracane, więc za każdym razem otrzymujesz tę samą tablicę. (Zobacz zachowanie tablic podczas kopiowania przy zapisie).

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

Przez wiele lat byliśmy w stanie definiować tablice jako stałe, nie sądzę, aby rozwiązywanie obejść było zbyt cenne.
miken32

1
@ miken32, chociaż prawda, dostarczone rozwiązanie jest interesujące, nie zostało dostarczone przez nikogo innego i może być koncepcyjnie zastosowane w innych językach w razie potrzeby (dodaj go do skrzynki z narzędziami)
puiu

1

jeśli używasz PHP 7 i 7+, możesz również użyć takiego pobierania

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

0

Stałe mogą zawierać tylko wartości skalarne, sugeruję przechowywanie serializacji (lub reprezentacji zakodowanej w JSON) tablicy.


1
Nie dodaje to niczego do zaakceptowanej odpowiedzi, więc może należy ją usunąć?
Ian Dunn

4
@IanDunn: Argumentowałbym, że przyjęta odpowiedź nie wyjaśnia, dlaczego, ani że nie dodaje niczego do mojej odpowiedzi, ale ... Możesz jednak głosować, aby ją usunąć.
Alix Axel

1
Naprawdę nie widzę sensu żadnej reprezentacji ciągu pożądanej tablicy.
Tomáš Zato - Przywróć Monikę
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.