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.