Constantes PHP que contienen matrices?

408

Esto falló:

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

Aparentemente, las constantes no pueden contener matrices. ¿Cuál es la mejor manera de evitar esto?

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

//...

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

Esto parece un esfuerzo innecesario.

Nick Heiner
fuente
17
PHP 5.6 admite matrices constantes, vea mi respuesta a continuación.
Andrea
1
¿Cuándo necesitaría usar una matriz como una constante, está tratando de hacer una enumeración? Si es así, utilice SplEnum: php.net/manual/en/class.splenum.php
ziGi
2
@ziGi Encontró este problema hoy, tiene diferentes tipos de imágenes para almacenar que requieren dimensiones específicas, se volvió útil almacenar estas dimensiones como matrices constantes en lugar de una para ancho y otra para altura.
Matt K

Respuestas:

499

NOTA: si bien esta es la respuesta aceptada, vale la pena señalar que en PHP 5.6+ puede tener matrices constantes; consulte la respuesta de Andrea Faulds a continuación .

También puede serializar su matriz y luego ponerla en la constante:

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

# use it
$my_fruits = unserialize (FRUITS);
Comunidad
fuente
40
Solo quiero decir que amo esta solución :)
GateKiller
16
Agradable. Pero el punto negativo es que no puede definir una constante de clase de esta manera.
Gregoire
19
es mejor atenerse a las variables estáticas en una clase.
Jürgen Paul
55
Lástima que no puedas hacer:$fruit = FRUITS[0];
Sophivorus
20
Este código es elegante pero bastante lento. Es mucho mejor usar un método de clase estática pública que devuelva la matriz.
sustantivo
844

Desde PHP 5.6, puede declarar una matriz constante con const:

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

La sintaxis corta también funciona, como era de esperar:

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

Si tiene PHP 7, finalmente puede usar define(), tal como lo había intentado por primera vez:

<?php
define('DEFAULT_ROLES', array('guy', 'development team'));
Andrea
fuente
41
Esto debe ser votado ya que todas las otras respuestas están desactualizadas o simplemente escritas por usuarios mal informados.
Andreas Bergström
¿Es esa la única sintaxis? ¿Eres capaz de usar la antigua función de definición? define ('ARRAY_CONSTANT', matriz ('item1', 'item2', 'item3'));
Jack
55
@JackNicholsonn Lamentablemente, no puede usarlo define()aquí en PHP 5.6, pero esto se ha solucionado para PHP 7.0 . :)
Andrea
@ AndreasBergström No, esta pregunta es demasiado nueva. Esta pregunta se hizo en 2009! Esta sintaxis será casi inútil para la mayoría de los usuarios hoy en día. Casi cualquiera tiene PHP 5.6 en sus servidores. Las otras respuestas están perfectamente bien, ya que también ofrecen alternativas. La respuesta aceptada es la única forma viable hasta ahora, si no desea utilizar clases.
Ismael Miguel
@IsmaelMiguel no esté tan seguro de que todos tengan 5.6. Cualquiera en el servidor de Windows acaba de obtener los controladores de servidor de 5.6 sql de Microsoft hace aproximadamente un mes.
MH
141

Puede almacenarlos como variables estáticas de una clase:

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

Si no le gusta la idea de que otros puedan cambiar la matriz, un getter podría ayudarlo:

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

EDITAR

Desde PHP5.4, incluso es posible acceder a valores de matriz sin la necesidad de variables intermedias, es decir, los siguientes trabajos:

$x = Constants::getArray()['index'];
soulmerge
fuente
1
+1. Voy por esto durante años:const AtomicValue =42; public static $fooArray = ('how','di')
Frank Nocke
99
Si bien me parece ridículo que no podamos crear matrices inmutables en php, esto proporciona una solución decente.
Akoi Meexx
Si está utilizando la constante mucho, definitivamente evitaría una llamada a función, son bastante caras. Estático es el camino a seguir.
Chris Seufert
1
Esta solución fue mucho más sorprendente de lo que esperaba: solo necesitaba parte de los valores de la matriz, por lo tanto, en lugar de simplemente obtener la matriz, usé algunos parámetros en la función. En mi caso, Constants :: getRelatedIDs ($ myID) me da una matriz interna con solo los valores que necesitaba (también hago una validación de ID dentro de esta función). @cseufert obtener toda la matriz y filtrar para cada caso sería mucho más costoso para mí ...
Armfoot
1
tener una función (getArray) con un miembro estático privado es la mejor representación para las constantes, ya que pueden ser cambios 👍🏻
Kamaldeep singh Bhatia
41

Si está utilizando PHP 5.6 o superior, use la respuesta de Andrea Faulds

Lo estoy usando así. Espero que ayude a otros.

config.php

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

En el archivo, donde necesito constantes.

require('config.php');
print_r(app::config('app_id'));
Jashwant
fuente
Hice lo mismo que tú. Entonces estaba buscando la optimización del rendimiento si esto es bueno o algo mejor.
NullPointer
Ya estoy de acuerdo con esta solución. Como es simple y fácil de entender ...
Faris Rayhan
12

Esto es lo que yo uso. Es similar al ejemplo proporcionado por soulmerge, pero de esta manera puede obtener la matriz completa o solo un valor único en la matriz.

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

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

Úselo así:

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

Puede almacenarlo como una cadena JSON en una constante. Y desde el punto de vista de la aplicación, JSON puede ser útil en otros casos.

define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));    
$fruits = json_decode (FRUITS);    
var_dump($fruits);
Mahesh Talpade
fuente
Esto es exactamente lo que estaba pensando. ¿No es esta una respuesta legítimamente buena?
Con Antonakos
Esto funciona muy bien con AngularJS porque consume JSON. Siento que esto es mucho mejor que la respuesta de serialización, pero ¿hay alguna razón por la cual la serialización es mejor? ¿Es más rápido quizás?
Drellgor
Sí, serializar es técnicamente más rápido. Sin embargo, para conjuntos pequeños, que es lo que más se necesita, prefiero este método ya que es más seguro. Cuando no se serializa, el código podría ejecutarse. Incluso si en este caso este es un riesgo muy bajo, creo que deberíamos reservar el uso o anular la serialización solo para casos extremos.
Mario Awad
9

A partir de PHP 5.6, puede definir matrices constantes utilizando la constpalabra clave como a continuación

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

y se puede acceder a diferentes elementos de la siguiente manera:

echo DEFAULT_ROLES[1]; 
....

Comenzando con PHP 7, las matrices constantes se pueden definir de la definesiguiente manera:

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

y se puede acceder a diferentes elementos de la misma manera que antes.

Altaf Hussain
fuente
3

Sé que es una pregunta un poco vieja, pero aquí está mi solución:

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

Lo definí porque necesitaba almacenar objetos y matrices en constantes, así que también instalé runkit en php para poder hacer que la variable $ const sea superglobal.

Puedes usarlo como $const->define("my_constant",array("my","values"));o solo$const->my_constant = array("my","values");

Para obtener el valor simplemente llame $const->my_constant;

Rikudou Sennin
fuente
Wow, no esperaba tal cosa ... ni siquiera lo sabía __gety __set... debo decir que este método es genial.
RedClover
Estos se llaman métodos mágicos, consulte la documentación de php sobre ellos.
Rikudou_Sennin
3

PHP 7+

A partir de PHP 7, puede usar el define () para definir una matriz constante:

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

echo ANIMALS[1]; // outputs "cat"
Rabin Lama Dong
fuente
3

Incluso puede trabajar con matrices asociativas ... por ejemplo en una clase.

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
fuente
2

Usando la función de explosión e implosión podemos improvisar una solución:

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

Esto hará eco email .

Si desea optimizarlo más, puede definir 2 funciones para hacer las cosas repetitivas por usted de esta manera:

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

Espero que ayude . Feliz codificación

MARYLAND. Sahib Bin Mahboob
fuente
puedes evitar explotar dos veces haciendo: $ explodeResult = explotar (',', $ const); if (isset ($ explodeResult) [$ index]) {return $ explodeResult [$ index];}
Saeed
@Saeed sí, ese es un buen punto. Actualizaré mi respuesta en consecuencia
MD. Sahib Bin Mahboob
2

Hacer algún tipo de truco de ser / deser o codificar / decodificar parece feo y requiere que recuerdes exactamente lo que hiciste cuando intentas usar la constante. Creo que la variable estática privada de clase con acceso es una solución decente, pero te haré una mejor. Solo tenga un método público de obtención estático que devuelva la definición de la matriz constante. Esto requiere un mínimo de código adicional y la definición de la matriz no puede modificarse accidentalmente.

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

initMyRoles( UserRoles::getDefaultRoles() );

Si realmente quiere que parezca una constante definida, puede darle un nombre en mayúsculas, pero sería confuso recordar agregar los paréntesis '()' después del nombre.

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

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

Supongo que podría hacer que el método sea global para estar más cerca de la funcionalidad de define () que estaba solicitando, pero de todos modos debería determinar el nombre constante y evitar los globales.

Daniel Skarbek
fuente
2

Puedes definir así

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

$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);
Fawwad
fuente
2

Sí, puede definir una matriz como constante. Desde PHP 5.6 en adelante , es posible definir una constante como una expresión escalar, y también es posible definir una constante de matriz . Es posible definir constantes como un recurso, pero debe evitarse, ya que puede causar resultados inesperados.

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

Con la referencia de este enlace

Que tengan una feliz codificación.

Sahil Patel
fuente
1

Si está buscando esto desde 2009, y no le gusta AbstractSingletonFactoryGenerators, aquí hay algunas otras opciones.

Recuerde, las matrices se "copian" cuando se asignan, o en este caso, se devuelven, por lo que prácticamente obtiene la misma matriz cada vez. (Consulte el comportamiento de copia en escritura de las matrices en 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
fuente
Hemos podido definir matrices como constantes durante muchos años, ya no creo que haya mucho valor para obtener soluciones alternativas.
miken32
1
@ miken32 mientras que la verdadera, la solución aportada es interesante, no fue suministrado por cualquier otra persona, y se puede aplicar conceptualmente a otros idiomas, según sea necesario (agregarlo a su caja de herramientas)
puiu
1

si está usando PHP 7 y 7+, también puede usar fetch como este

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

Las constantes solo pueden contener valores escalares, le sugiero que almacene la serialización (o representación codificada en JSON) de la matriz.

Alix Axel
fuente
1
Esto no agrega nada a la respuesta aceptada, ¿tal vez debería eliminarse?
Ian Dunn
44
@IanDunn: Yo diría que la respuesta aceptada no explica por qué, o que no agrega nada a mi respuesta pero ... Sin embargo, siéntase libre de votar para eliminar.
Alix Axel
1
Realmente no veo el punto de ninguna representación de cadena de la matriz deseada.
Tomáš Zato - Restablece a Mónica el