Constantes PHP contendo matrizes?

408

Isso falhou:

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

Aparentemente, as constantes não podem conter matrizes. Qual é a melhor maneira de contornar isso?

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

//...

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

Isso parece um esforço desnecessário.

Nick Heiner
fonte
17
O PHP 5.6 suporta matrizes constantes, veja minha resposta abaixo.
Andrea
1
Quando você precisaria usar uma matriz como uma constante, você está tentando fazer uma enumeração? Em caso afirmativo, use SplEnum: php.net/manual/en/class.splenum.php
ziGi
2
O @ziGi chegou a esse problema hoje, possui diferentes tipos de imagens para armazenar que exigem dimensões específicas, tornou-se útil armazenar essas dimensões como matrizes constantes, em vez de uma para largura e outra para altura.
Matt K

Respostas:

499

NOTA: enquanto esta é a resposta aceita, vale a pena notar que no PHP 5.6+ você pode ter arrays const - veja a resposta de Andrea Faulds abaixo .

Você também pode serializar sua matriz e depois colocá-la na constante:

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

# use it
$my_fruits = unserialize (FRUITS);
Comunidade
fonte
40
Só quero dizer que te amo esta solução :)
GateKiller
16
Agradável. Mas o ponto negativo é que você não pode definir uma constante de classe dessa maneira.
Gregoire
19
é melhor ficar com variáveis ​​estáticas em uma classe.
Jürgen Paul
5
Pena que você não pode fazer:$fruit = FRUITS[0];
Sophivorus 22/03
20
Este código é elegante, mas bem lento. É muito melhor usar um método público de classe estática que retorna a matriz.
substantivo
844

Desde o PHP 5.6, você pode declarar uma matriz constante com const:

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

A sintaxe curta também funciona, como seria de esperar:

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

Se você possui o PHP 7, pode finalmente usar define(), exatamente como havia tentado:

<?php
define('DEFAULT_ROLES', array('guy', 'development team'));
Andrea
fonte
41
Isso precisa ser votado, pois todas as outras respostas estão desatualizadas ou apenas escritas por usuários desinformados.
Andreas Bergström
Essa é a única sintaxe? Você é capaz de usar a função de definição antiga? define ('ARRAY_CONSTANT', matriz ('item1', 'item2', 'item3'));
22414 Jack
5
@JackNicholsonn Infelizmente você não pode usar define()aqui no PHP 5.6, mas isso foi corrigido no PHP 7.0 . :)
Andrea
@ AndreasBergström Não, esta pergunta é muito nova. Esta pergunta foi feita em 2009! Essa sintaxe será quase inútil para a maioria dos usuários atualmente. Quase todo mundo tem o PHP 5.6 em seus servidores. As outras respostas são perfeitamente boas, pois também oferecem alternativas. A resposta aceita é a única maneira viável até agora, se você não quiser usar classes.
Ismael Miguel
@IsmaelMiguel não tenha tanta certeza de que todos têm o 5.6. Qualquer pessoa no servidor Windows agora conseguiu os drivers de servidor 5.6 sql da microsoft há cerca de um mês.
MH
141

Você pode armazená-los como variáveis ​​estáticas de uma classe:

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

Se você não gosta da ideia de que a matriz pode ser alterada por outras pessoas, um getter pode ajudar:

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

EDITAR

Desde o PHP5.4, é possível acessar valores de array sem a necessidade de variáveis ​​intermediárias, ou seja, o seguinte funciona:

$x = Constants::getArray()['index'];
soulmerge
fonte
1
+1. Vou fazer isso há anos:const AtomicValue =42; public static $fooArray = ('how','di')
Frank Nocke
9
Embora me pareça ridículo que não possamos criar matrizes imutáveis ​​no php, isso fornece uma solução decente.
Akoi Meexx
Se você estiver usando muita constante, eu definitivamente evitaria uma chamada de função, elas são muito caras. Estático é o caminho a percorrer.
Chris Seufert
1
Essa solução foi muito mais impressionante do que eu esperava: eu só precisava de parte dos valores da matriz, portanto, em vez de simplesmente obter a matriz, usei alguns parâmetros na função. No meu caso, Constants :: getRelatedIDs ($ myID) me fornece uma matriz interna com apenas os valores que eu precisava (eu também faço alguma validação de ID nessa função). @cseufert recebendo toda a matriz e filtragem para cada caso seria muito mais caro para mim ...
Armfoot
1
tendo uma função (GetArray) com membro estático privado é melhor representação para constantes como eles podem ser mudanças 👍🏻
Kamaldeep Singh Bhatia
41

Se você estiver usando o PHP 5.6 ou superior, use a resposta de Andrea Faulds

Eu estou usando assim. Espero que ajude os outros.

config.php

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

Em arquivo, onde eu preciso de constantes.

require('config.php');
print_r(app::config('app_id'));
Jashwant
fonte
Eu fiz o mesmo que você. Então, estava procurando por otimização de desempenho, se isso é bom ou outra coisa, se melhor.
NullPointer
Sim, eu concordo com esta solução. Como é simples e fácil de ser entendido ...
Faris Rayhan
12

É isso que eu uso. É semelhante ao exemplo fornecido pelo soulmerge, mas dessa forma você pode obter a matriz completa ou apenas um valor único na 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;
    }
}

Use-o assim:

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

Você pode armazená-lo como uma sequência JSON em uma constante. E do ponto de vista da aplicação, o JSON pode ser útil em outros casos.

define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));    
$fruits = json_decode (FRUITS);    
var_dump($fruits);
Mahesh Talpade
fonte
Era exatamente isso que eu estava pensando. Esta não é uma resposta legitimamente boa?
Con Contekakos1
Isso funciona muito bem com o AngularJS porque consome JSON. Eu sinto que isso é muito melhor que a resposta serializada, mas há alguma razão pela qual serializar é melhor? Talvez seja mais rápido?
Drellgor 19/09/14
Sim, serializar é tecnicamente mais rápido. No entanto, para pequenos conjuntos, o que é necessário principalmente, prefiro esse método, pois é mais seguro. Quando você desserializa, o código pode ser executado. Mesmo que neste caso seja um risco muito baixo, acho que devemos reservar o uso ou desserializar apenas em casos extremos.
Mario Awad
9

A partir do PHP 5.6, você pode definir matrizes constantes usando constpalavras-chave como abaixo

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

e diferentes elementos podem ser acessados ​​como abaixo:

echo DEFAULT_ROLES[1]; 
....

A partir do PHP 7, matrizes constantes podem ser definidas usando-se definecomo abaixo:

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

e diferentes elementos podem ser acessados ​​da mesma maneira que antes.

Altaf Hussain
fonte
3

Eu sei que é uma pergunta um pouco antiga, mas aqui está a minha solução:

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

Eu o defini porque precisava armazenar objetos e matrizes em constantes, então instalei também o runkit no php para poder tornar a variável $ const superglobal.

Você pode usá-lo como $const->define("my_constant",array("my","values"));ou apenas$const->my_constant = array("my","values");

Para obter o valor, basta chamar $const->my_constant;

Rikudou_Sennin
fonte
Uau, eu não esperava isso ... eu nem sabia __gete __set... devo dizer que esse método é ótimo.
RedClover 10/03/19
Estes são chamados métodos mágicos, verifique a documentação php sobre eles.
Rikudou_Sennin
3

PHP 7+

No PHP 7, você pode simplesmente usar a função define () para definir uma matriz constante:

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

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

Pode até trabalhar com matrizes associativas. Por exemplo, em uma classe.

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

Usando a função explodir e implodir, podemos improvisar uma solução:

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

Isso ecoará email.

Se você deseja otimizá-lo mais, você pode definir 2 funções para fazer as coisas repetitivas para você assim:

//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 ajude . Feliz codificação.

MD. Sahib Bin Mahboob
fonte
você pode impedir a explosão duas vezes fazendo: $ explodeResult = explode (',', $ const); if (isset ($ explodeResult) [$ index]) {return $ explodeResult [$ index];}
Saeed
@ Saeed sim, que é um bom ponto. Vou atualizar minha resposta de acordo
MD. Sahib Bin Mahboob
2

Fazer algum tipo de truque de ser / deser ou codificar / decodificar parece feio e exige que você se lembre exatamente do que fez quando está tentando usar a constante. Eu acho que a variável estática privada de classe com o acessador é uma solução decente, mas farei uma melhor. Basta ter um método público getter estático que retorne a definição da matriz constante. Isso requer um mínimo de código extra e a definição da matriz não pode ser modificada acidentalmente.

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

initMyRoles( UserRoles::getDefaultRoles() );

Se você realmente quer fazer com que pareça uma constante definida, pode dar um nome com maiúsculas, mas seria confuso lembrar de adicionar os parênteses '()' após o nome.

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

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

Suponho que você possa tornar o método global mais próximo da funcionalidade define () que estava solicitando, mas realmente deve definir o nome da constante de qualquer maneira e evitar globais.

Daniel Skarbek
fonte
2

Você pode definir assim

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

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

Sim, você pode definir uma matriz como constante. A partir do PHP 5.6 , é possível definir uma constante como uma expressão escalar, e também é possível definir uma constante da matriz . É possível definir constantes como um recurso, mas deve ser evitado, pois pode 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"
?>

Com a referência deste link

Tenha uma codificação feliz.

Sahil Patel
fonte
1

Se você está procurando isso em 2009 e não gosta de AbstractSingletonFactoryGenerators, aqui estão algumas outras opções.

Lembre-se de que as matrizes são "copiadas" quando atribuídas ou, nesse caso, retornadas, portanto, você praticamente obtém a mesma matriz sempre. (Veja o comportamento de cópia na gravação de matrizes em 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
fonte
Conseguimos definir matrizes como constantes há muitos anos, acho que não há muito valor em soluções alternativas obtusas.
miken32
1
@ miken32 enquanto verdade, a solução fornecida é interessante, não foi fornecido por qualquer outra pessoa, e pode ser conceitualmente aplicados a outros idiomas, conforme necessário (adicioná-lo à sua caixa de ferramentas)
puiu
1

se você estiver usando PHP 7 e 7+, também pode usar a busca assim

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

As constantes podem conter apenas valores escalares. Sugiro que você armazene a serialização (ou representação codificada em JSON) da matriz.

Alix Axel
fonte
1
Isso não adiciona nada à resposta aceita, talvez deva ser excluída?
Ian Dunn
4
@IanDunn: Eu diria que a resposta aceita não explica o porquê ou que não acrescenta nada à minha resposta, mas ... Sinta-se à vontade para votar para excluir.
Alix Axel
1
Realmente não vejo o ponto de nenhuma representação de string da matriz desejada.
Tomáš Zato - Restabelece Monica 15/01